Toast UI Editor 实现图片粘贴上传到七牛云

盖马鲁
2023-12-01

Toast UI Editor介绍

  • 一款支持Markdown、WYSIWYG模式的编辑器
  • Github

实现步骤

0. 准备工作
npm install @toast-ui/editor
npm install @toast-ui/editor-plugin-color-syntax
npm install @toast-ui/editor-plugin-code-syntax-highlight
npm install @toast-ui/editor-plugin-chart
npm install @toast-ui/editor-plugin-uml
npm install @toast-ui/editor-plugin-table-merged-cell
1. 去除默认的addImageBlobHook监听事件

Toast UI Editor支持三种图片上传方式:弹窗、拖拽、截屏粘贴。查看文档并测试可知,三种上传方式最终都会被addImageBlobHook监听,并处理为Base64格式的图片。
所以,第一步,我们要去除默认的addImageBlobHook监听事件

  • 此处为默认的addImageBlobHook监听事件,位于src/js/importManager.js中
 /**
   * Initialize default image importer
   * @private
   */
  _initDefaultImageImporter() {
    this.eventManager.listen('addImageBlobHook', (blob, callback) => {
      const reader = new FileReader();

      reader.onload = event => {
        callback(event.target.result);
      };

      reader.readAsDataURL(blob);
    });
  }
  • eventManager.js中提供了删除监听事件的函数removeEventHandler(typeStr, handler)
  /**
   * Remove event handler from given event type
   * @param {string} typeStr Event type name
   * @param {function} [handler] - registered event handler
   */
  removeEventHandler(typeStr, handler) {
    const { type, namespace } = this._getTypeInfo(typeStr);

    if (type && handler) {
      this._removeEventHandlerWithHandler(type, handler);
    } else if (type && !namespace) {
      // dont use dot notation cuz eslint
      this.events.delete(type);
    } else if (!type && namespace) {
      this.events.forEach((eventHandlers, eventType) => {
        this._removeEventHandlerWithTypeInfo(eventType, namespace);
      });
    } else if (type && namespace) {
      this._removeEventHandlerWithTypeInfo(type, namespace);
    }
  }
  • 删除监听事件
// 删除默认监听事件
this.editor.eventManager.removeEventHandler('addImageBlobHook')
2. 添加自定义的addImageBlobHook监听事件
    // 添加自定义监听事件
    this.editor.eventManager.listen('addImageBlobHook', (blob, callback) => {
      // 此处填写自己的上传逻辑,url为上传后的图片地址
      this.upload(blob, url => {
        callback(url)
      })
    })
3. 实现自己的上传逻辑

实现文件上传

4. 最终结果

完美解决三种方式(Popup、Drag、Screenshot)按照自己的上传逻辑进行图片上传

完整源码

  • Toast UI Editor 版本
    "@toast-ui/editor": "^2.1.2"

  • 基于vue的源码示例

<template>
  <div ref="toastUIEditor" />
</template>

<script>
import 'codemirror/lib/codemirror.css'
import '@toast-ui/editor/dist/toastui-editor.css'
import 'tui-color-picker/dist/tui-color-picker.css'

import Editor from '@toast-ui/editor'
import colorSyntax from '@toast-ui/editor-plugin-color-syntax'

export default {
  name: 'Markdown',
  data() {
    return {
      editor: null
    }
  },
  mounted() {
    const options = {
      el: this.$refs.toastUIEditor,
      previewStyle: 'vertical',
      height: '500px',
      initialEditType: 'markdown',
      initialValue: 'Select some text and choose a color from the toolbar.',
      plugins: [colorSyntax]
    }
    this.editor = new Editor(options)
    // 删除默认监听事件
    this.editor.eventManager.removeEventHandler('addImageBlobHook')
    // 添加自定义监听事件
    this.editor.eventManager.listen('addImageBlobHook', (blob, callback) => {
      // 此处填写自己的上传逻辑,url为上传后的图片地址
      this.upload(blob, url => {
        callback(url)
      })
    })
  },
  methods: {
    /**
     * 上传至服务器
     */
    upload(file, callback) {
      const formData = new FormData()
      formData.append('file', file)
      const ajax = new XMLHttpRequest()
      ajax.open('POST', 'http://localhost:9100/qiniu/upload', true)
      ajax.send(formData)
      ajax.onreadystatechange = function() {
        if (ajax.readyState === 4) {
          if ((ajax.status >= 200 && ajax.status < 300) || ajax.status === 304) {
            console.log('上传成功')
            const obj = JSON.parse(ajax.responseText)
            callback(obj.result)
          }
        }
      }
    }
  }
}
</script>

 类似资料: