【wangEditor 5】在线解析本地word,将内容展现在wangEditor中

莫骞仕
2023-12-01

最近有个问题,在word中复制的多张图片,或者同时复制了图片和文字,图片粘贴到编辑器中不显示。

原因很简单:浏览器无法直接访问本地资源下的文件,切记这一点,不要试图用浏览器直接访问你本地文件。因为从技术角度来讲,这样是非常危险的,这也是我在尝试了一天后下班在路上才反应过来的。

Not allowed to load local resource: 
file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg

所以在沟通后,需求就从直接复制变成了在线解析word,这样根据我前几天的经验,瞬间就变得简单了很多

技术点

FileReader

FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
我们用到了FileReader的readAsArrayBuffer方法,该方法的作用为:启动读取指定的 Blob 或 File 内容,当读取操作完成时,返回一个 ArrayBuffer 对象以表示所读取文件的数据
使用方法:

		const reader = new FileReader();
        reader.onload = function (evt: any) {//当文件读取完毕后
          console.log(evt)
        }
        reader.readAsArrayBuffer(file);// 启动读取指定的 Blob 或 File 内容

mammoth

这个依赖会将word解析成HTML,真的是超级好用,安装

npm install mammoth --save

思路

1、新建一个input标签,设置type为file,隐藏这个标签
2、在wangEditor注册一个自定义菜单,点击它的时候调用input,进行文件选择上传
3、使用FileReader读取对象
4、使用mammoth将word解析成html
5、将HTML展现在富文本编辑器上

操作

1、新建一个input标签,设置type为file,隐藏这个标签,设置只能选择word文档,通过change事件获取选择的文件,使用mammoth解析后将HTML展现在富文本编辑器上

<input v-show="false" id="changeFile" ref="fileRef" type="file" @change="fileChange" accept=".doc,.docx">
	//文件选择事件
	async fileChange(res: any) {
      if (res.srcElement.files && res.srcElement.files.length > 0) {//判断是否选择了文件
        const value: any = await this.analysisWord(res.srcElement.files[0])//解析word
        const editor: any = this.editor//editor的定义在富文本加载时事件中,可以去官网文档看onCreated方法
        editor.dangerouslyInsertHtml(value)//粘贴html格式的内容
        res.target.value=''//一定要清空,不然连续两次选择同一文件会不触发本事件
      }
    },
    
    //解析word
    analysisWord(file: any) {
      return new Promise((resolve) => {
        const reader = new FileReader();
        reader.onload = function (evt: any) {//当文件读取完毕后
          mammoth//调用mammoth组件的方法进行解析文件
            .convertToHtml({ arrayBuffer: evt.target.result })
            .then(function (resultObject) {
              resolve(resultObject.value);//将处理好的html数据返回
            });
        }
        reader.readAsArrayBuffer(file);// 启动读取指定的 Blob 或 File 内容 :https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/readAsArrayBuffer
      })
    },

2、注册菜单,本部门建议参照教程,已经写的非常细致了,我会把自己的ts文件放在下面,可以用作参考,重点在最后的emit

import { IButtonMenu, IDomEditor } from '@wangeditor/editor'

class MyWordMenu implements IButtonMenu {
    public title:string; //菜单标题
    public tag:string; //菜单类型
    public iconSvg:string; //按钮图标,可为空
    constructor() {
        this.title = '解析word' // 自定义菜单标题
        this.iconSvg='<svg>...</svg>'
        this.tag = 'button'
    }

    // 获取菜单执行时的 value ,用不到则返回空 字符串或 false
    getValue(editor: IDomEditor): string | boolean {
        return false
    }

    // 菜单是否需要激活(如选中加粗文本,“加粗”菜单会激活),用不到则返回 false
    isActive(editor: IDomEditor): boolean {
        return false
    }

    // 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false
    isDisabled(editor: IDomEditor): boolean {
        return false
    }
    // 点击菜单时触发的函数
    exec(editor: IDomEditor, value: string | boolean) {
        if (this.isDisabled(editor)) return
        editor.emit('open-word')//这里通知页面触发了点击事件
    }

}
export default MyWordMenu;

3、当监听到点击事件后,手动触发input,打开文件选择窗口,这两行代码我是放在了onCreated事件中

	  //富文本加载时
    onCreated(editor: any) {
      this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
      const toolbarConfig: any = this.toolbarConfig
      toolbarConfig.insertKeys = {//插入自定义的菜单
        index: 20, // 插入的位置,基于当前的 toolbarKeys
        keys: ['openWord']
      }
	  //下面就是监听事件了
      const editor1: any = this.editor
      editor1.on('open-word', this.openWord)//监听开启word解析功能


    },
    //开启文本解析功能并打开文件选择器
    openWord() {
      const changeFile: any = document.getElementById("changeFile")
      changeFile.click();
    },

效果如下

wangEdit-解析word

Demo

https://gitee.com/zhao-liangchao/wang-edit5-word
(包含复制粘贴word图片与文字混合内容解决方案)

 类似资料: