前端 2020-06-20 17:18:27

使用富文本编辑器过程中,上传图片大多需要点击工具栏手动选择图片文件上传,相对繁琐。希望新增复制图片到编辑器自动上传图片文件提高效率。

实现原理

我们通过通过监听浏览器的paste事件,获取事件中对应的剪贴板数据,从中解析出对应的图片文件信息。再调用对应的图片上传接口将其转换为远程url,最后通过富文本编辑器的插入图片api,插入到文档中。

paste事件

window.addEventListener('paste', this.onPaste, false);

onPaste = (e) => {
    // e.clipboardData是 DataTransfer类型的对象
}

DataTransfer

DataTransfer.items包含了复制操作后剪贴板中的数据

DataTransferItem getAsFile

通过getAsFile获取获取到DataTransferItem实例重的文件对象

实现流程

  1. 监听富文本编辑器的粘贴事件
this.quillInstance = this.quillRef.editor;
this.quillInstance.root.addEventListener('paste', this.onQuillPaste, false);
  1. paste事件处理,获取
onQuillPaste = async (e) => {
    const { clipboardData } = e;

    if (clipboardData) {
      // https://caniuse.com/#feat=mdn-api_datatransfer_files
      // DataTransfer API: files chrome 83开始支持,safari暂不支持
      // https://caniuse.com/#feat=mdn-api_datatransfer_items
      // DataTransfer API: items chrome 支持,最新的safari支持
      // DataTransferItem API: getAsFile chrome 11开始支持
      // 为了兼容性使用clipboardData.items
      const { items } = clipboardData;

      if (!items) {
        message.error('当前浏览器不支持自动上传图片,请手动上传或者使用chrome浏览器~');
        return;
      }
      if (items.length === 0) {
        return;
      }
      // 类数组转换为数组
      const imageItems = [...items].filter(isImageItem);
      const imageFiles = imageItems.map(imageItem => imageItem.getAsFile());

      imageFiles.forEach(async (imageFile) => {
        if (this.props.enableAutoUpload) {
          // 当粘贴内容是文件的时候,阻止默认的图片粘贴,否则会出现两张相同图片
          e.preventDefault();
          this.uploadImage({
            imageFile,
            success: (imageUrl) => {
              this.insertImage(imageUrl);
            },
          });
        } else {
          // 直接使用默认的粘贴操作
          // const base64Data = await toBase64(imageFile);
          // this.insertImage(base64Data);
        }
      });
    }
  }
  1. 光标位置插入图片
insertImage(url) {
    const { index } = this.quillRef.getEditor().getSelection();

    this.quillRef.getEditor().insertEmbed(index, 'image', `${url}`);
    this.quillRef.getEditor().setSelection(index + 1);
  }

问题

兼容性

windows系统中剪贴板获取不到系统里的文件信息,比如文件管理器、doc文档(doc文档实际也是本地文件系统里的图片)。 原生quill在windows系统下也无法复制图片,生成base64数据。 截图工具中的图片粘贴到富文本中可以正常上传

参考资料

  1. DataTransfer
  2. DataTransferItem.getAsFile()