文件的导入导出
在最近的项目中有一个需求是将前端页面上的一个表格导出成word文档,和将word文档解析渲染到页面上用户确定之后再传到后台储存,第一次遇到这种功能,也是找了好久才找到解决方法,不知道对不对,反正实现了,哈哈哈
所以记录下来方便以后再遇到好用CV大法。
导入
首先是导出功能,我用的是Element UI的el-upload组件,用input type=file也行,但是用户需求只要导入docx类型,就用了这个组件,也可以限制文件类型
<el-upload v-if="closemb" action="#" :file-list='fileList' accept=".docx" :before-upload='(file, list)=>uploadBeforeUpload(file, list)'>
<el-button slot="trigger" size="small" type="primary" style="font-size: 13px;"><i class="el-icon-tickets"></i>导入模板</el-button>
</el-upload>
然后在上传文件之前的钩子上绑定解析文件的方法
uploadBeforeUpload(file) {
const fileReader = new FileReader();
// 以二进制方式打开文件
fileReader.readAsArrayBuffer(file);
fileReader.onload = (event) => {
const { result } = event.target;
mammoth.convert({ arrayBuffer: result }).then(this.displayResult).done()
}
},
忘说了还要下这些插件
import mammoth from 'mammoth'
import E from 'wangeditor'
import FileSaver from 'file-saver'
import htmlDocx from 'html-docx-js/dist/html-docx'
然后是渲染到页面上的方法
displayResult(result) {
if (result.value == "") {
this.$message.warning('未发生改变,导入失败')
return
}
document.querySelector('#tablebody').style.display = 'none'
if (!this.editor) {
this.editor = new E('#daoru')
this.editor.create()
}
document.querySelector('#daoru').style.display = 'block'
document.querySelector('.w-e-text-container').style.height = '780px'
this.closemb = false
let htmlValue = result.value
document.querySelector('.w-e-text').innerHTML = htmlValue
document.querySelector('.w-e-toolbar').style.display = 'none'
},
因为甲方爸爸说要在页面上也能编辑,虽然我百思不得其解为什么不编辑好了再导入还非要在页面上也能编辑但是如果解析了也变成table标签然后渲染到页面上太麻烦了(主要还是不会),所以干脆搞了个富文本编辑器到页面上,导入后编辑器替代原来那个表的位置,表隐藏,导入后将导入按钮变成关闭导入,必须关了才能再重新导,别问为什么,问就是快。U1S1这编辑器功能太多了
恐再生事端,所以我就把这个功能栏给display=none了,不然指不定又要出啥需求
导出
然后是导出功能,需要下载html-docx-js插件,注意引入的时候是 from “html-docx-js/dist/html-docx”,我引入的时候想着引入html-docx-js就行吧,结果报错,找半天bug一直没怀疑到引入上。
daochu() {
let title = document.querySelector('.tabtopbody').innerHTML
let contentHtml = document.querySelector('.tabbottom').innerHTML.
if (document.querySelector('#tablebody').style.display == 'none') {
contentHtml = document.querySelector('.w-e-text').innerHTML +
`<h3>${timeType + this.formType}</h3><h3>作者:${this.authorinput}</h3>`
}
if (document.querySelector('#tablebody').style.display != 'none') {
contentHtml = `<h2 style="text-align:center">${title}</h2>` +
`<p>${timeType + this.formType}</p><p>作者:${this.authorinput}</p>` + contentHtml
}
let csshTML =
`
table{
width:100%;
table-layout:fixed;
margin-top:10px;
border:1px solid #ddd;
border-collapse:collapse;
height: 96%;
color: #bcbcbc;
text-align: center;
}
td{
border:1px solid #ddd;
color:#333;
text-align:center;
max-width:200px;
}
`
let content =
`<!DOCTYPE html><html>
<head>
<meta http-equiv="Content-Type" content="text/hmtl;charset=UTF-8">
<style>
${csshTML}
</style>
</head>
<body>
${contentHtml}
</body>
</html>`
let converted = htmlDocx.asBlob(content);
console.log(converted)
if (document.querySelector('#tablebody').style.display != 'none') {
FileSaver.saveAs(converted, `${title}.docx`)
} else {
FileSaver.saveAs(converted, `新建文档.docx`)
}
}
我是将表名作为了文件名,导出后发现有空格,所以用 .trim(),还有就是这个表格的内容在不是编辑器的时候也是可编辑的,我一开始想到就是全加成input不就好了,但是word好像识别不了input,内容就看不见,只有各种replace把input变成p标签或者其他的
然后又看了些资料,才看到有 contenteditable 这个属性是可以指定元素内容是否可编辑的,基础不牢,学习还是不能停啊。
后来又问我导入导出是互通的吗,就是刚导入的文件可以导出,刚导出的文件可以导入回来吗,虽然我直接
但是答案那必然是可以
刚导入的文件要导出
的话那就要获取编辑器里面的内容,所以要判断一下
至于文件名嘛,咱也不敢确定第一行就是标题啊,要什么自行车,自己重命名去吧
刚导出的文件要导入
不知道为啥导入后啥也没有,但是随便改一下,哪怕是Ctrl A 再 Crtl X 再 Ctrl V 再导入都有内容,有知道的大佬可以留言告诉我吗
没办法了,最后只想到
提醒他一下吧,文(nin)件(chi)未(bao)发(le)生(cheng)变(de)化(ba),所以导入失败,这样他应该就知道至少改改再传了吧~