最近有个问题,在word中复制的多张图片,或者同时复制了图片和文字,图片粘贴到编辑器中不显示。
原因很简单:浏览器无法直接访问本地资源下的文件,切记这一点,不要试图用浏览器直接访问你本地文件。因为从技术角度来讲,这样是非常危险的,这也是我在尝试了一天后下班在路上才反应过来的。
Not allowed to load local resource:
file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
所以在沟通后,需求就从直接复制变成了在线解析word,这样根据我前几天的经验,瞬间就变得简单了很多
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 内容
这个依赖会将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
https://gitee.com/zhao-liangchao/wang-edit5-word
(包含复制粘贴word图片与文字混合内容解决方案)