1.问题描述
在vue项目中使用jszip-utils+docxtemplater+pizzip+file-saver来写前端word导出功能,开发过程中可能会出现‘Can't find end of central directory : is this a zip file ?’报错。那么你要知道该报错是怎样被引起的?百度大部分帖子是关于如何使用综上所述一套组件写word导出功能方法,极少部分帖子是关于此报错的具体解决方案。
该报错的引起方式实际上是没有找到你的word模板,或者的它认为你的文件不是一个zip格式,所以会报错。
2.解决方式
我不禁去看了一下https://stuk.github.io/jszip/documentation/examples.html,该网站有JSZipUtils部分解释方式,并且提供了读取本地文件的方式。
但是当你选取一个非zip格式文件的时候它同样的也会报这个错误。难道是我们的文件格式有问题吗?其实并不完全是这样。
// 读取并获得模板文件的二进制内容
JSZipUtils.getBinaryContent('outputAllValue.docx', (error, content) => {
let e = null
let out = null
let zip = null
let doc = null
// 抛出异常
if (error) {
throw error
}
// 创建一个PizZip实例,内容为模板的内容
zip = new PizZip(content)
// 创建并加载docxtemplater实例对象
doc = new docxtemplater().loadZip(zip)
// 设置模板变量的值
doc.setData({
table: data,
totalPrice: totalPrice
})
try {
// 用模板变量的值替换所有模板变量
doc.render()
} catch (error) {
// 抛出异常
e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties
}
console.log(JSON.stringify({ error: e }))
throw error
}
// 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
})
// 将目标文件对象保存为目标类型的文件,并命名
saveAs(out, 'demo.docx')
})
如果你使用的代码片段与我类似,那么请注意 JSZipUtils.getBinaryContent('outputAllValue.docx', (error, content) 这个地方,JSZipUtils.getBinaryContent(path, option)提供path和option两个参数。首先说到path,前端开发最首先想到的可能是绝对路径或者相对路径。如果你用vue开发,你可能还会用到@这个符号作为根目录使用。
但是在使用JSZipUtils.getBinaryContent的时候,这个path我们应该这样写 'xxxxxxx.docx'(xxxxxxx指模板名称)。如我的模板名为outputAllValue.docx,那么我的路径为'/outputAllValue.docx'。
修改完这个地方之后,剩下的就是要知道你使用的vue-cli是版本2还是版本3。如果是2,则应该有一个static的文件夹,请见你的模板文件放入这个static文件夹中;如果是3,则有一个public文件夹,请将模板文件放入这个public文件夹中。
经过上面的两个更改,就不会再报相应的错误了。