在項目中,我們可以借助后端返回文件流實現(xiàn)文件下載娩嚼。如果前端有數(shù)據(jù)蘑险,也可以借助前端框架進(jìn)行下載。本文將介紹如何在前端純js實現(xiàn)word文檔導(dǎo)出岳悟。
1. 組件介紹
要實現(xiàn)前端純js導(dǎo)出word文檔佃迄,我們需要用到docxtemplater,jszip-utils贵少,file-saver三個組件呵俏,接下來簡要的介紹以下三個組件。
1.1 docxtemplater
docxtemplater 使用 JSON 數(shù)據(jù)格式作為輸入滔灶,可以處理docx 和 ppt模板普碎。不像一些其它的工具,比如 docx.js, docx4j, python-docx 等录平,需要自己編寫代碼來生成文件随常,docxtemplater只需要用戶通過標(biāo)簽的形式編寫模板,就可以生成文件萄涯。
貼一貼官網(wǎng)給的例子绪氛,我們將參考以下例子來實現(xiàn)。
var PizZip = require('pizzip');
var Docxtemplater = require('docxtemplater');
var fs = require('fs');
var path = require('path');
//Load the docx file as a binary
var content = fs
.readFileSync(path.resolve(__dirname, 'input.docx'), 'binary');
var zip = new PizZip(content);
var doc = new Docxtemplater();
doc.loadZip(zip);
//set the templateVariables
doc.setData({
first_name: 'John',
last_name: 'Doe',
phone: '0652455478',
description: 'New Website'
});
try {
// render the document (replace all occurences of {first_name} by John, {last_name} by Doe, ...)
doc.render()
}
catch (error) {
var e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties,
}
console.log(JSON.stringify({error: e}));
// The error thrown here contains additional information when logged with JSON.stringify (it contains a property object).
throw error;
}
var buf = doc.getZip()
.generate({type: 'nodebuffer'});
// buf is a nodejs buffer, you can either write it to a file or do anything else with it.
fs.writeFileSync(path.resolve(__dirname, 'output.docx'), buf);
1.2 jszip-utils
jszip-utils 提供一個getBinaryContent(path, data)接口涝影,path即是文件的路徑枣察,支持AJAX get請求,data為讀取的文件內(nèi)容燃逻。下面是官網(wǎng)給的例子序目。
// loading a file and add it in a zip file
JSZipUtils.getBinaryContent("path/to/picture.png", function (err, data) {
if(err) {
throw err; // or handle the error
}
var zip = new JSZip();
zip.file("picture.png", data, {binary:true});
});
1.3 file-saver
file-saver是一款適合在客戶端生成文件的工具,它提供的接口saveAs(blob, "1.docx")將會使用到伯襟。
2. 操作步驟
2.1 安裝
接下來就是安裝以上組件工具猿涨,安裝命令如下
-- 安裝 docxtemplater
cnpm install docxtemplater pizzip --save
-- 安裝 jszip-utils
cnpm install jszip-utils --save
-- 安裝 jszip
cnpm install jszip --save
-- 安裝 FileSaver
cnpm install file-saver --save
2.2 引入
在需要用到的組件中引入以上工具
import docxtemplater from 'docxtemplater'
import PizZip from 'pizzip'
import JSZipUtils from 'jszip-utils'
import {saveAs} from 'file-saver'
2.3 創(chuàng)建模板文件
我們要先創(chuàng)建一個模板文件,事先定義好格式和內(nèi)容姆怪。docxtemplater 之前介紹到是通過標(biāo)簽的形式來填充數(shù)據(jù)的叛赚,簡單的數(shù)據(jù)我們可以使用{} + 變量名來實現(xiàn)簡單的文本替換。
- 簡單的文本替換
如果在模板中稽揭,定義
hello {name}
在設(shè)置數(shù)據(jù)時俺附,定義
{name:'John'}
最終生成的文件,如下
hello John
有點像jsp中的變量解析溪掀。
- 循環(huán)輸出
稍微復(fù)雜點的像表格事镣,我們會傳遞一個數(shù)組。那這個表格標(biāo)簽實現(xiàn)起來挺簡單的揪胃,例子如下:
模板文件璃哟,定義如下:
{#products}
{name}, {price} €
{/products}
設(shè)置數(shù)據(jù)時氛琢,定義如下:
{
"products": [
{ name :"Windows", price: 100},
{ name :"Mac OSX", price: 200},
{ name :"Ubuntu", price: 0}
]
}
最終實現(xiàn)效果如下:
Windows, 100 €
Mac OSX, 200 €
Ubuntu, 0€
如果數(shù)組中的都是字符串,不是對象類型随闪,比如數(shù)據(jù)結(jié)構(gòu)如下
{
"products": [
"Windows",
"Mac OSX",
"Ubuntu"
]
}
那么阳似,模板文件中應(yīng)該這樣設(shè)置
{#products} {.} {/products}
最終的文件內(nèi)容如下:
Windows Mac OSX Ubuntu
還有一些其它的復(fù)雜標(biāo)簽,比輸支持條件判斷蕴掏,支持段落等等,筆者就不在這里一一贅述了调鲸。詳情參考官網(wǎng)文檔盛杰。筆者的要導(dǎo)出的比較簡單,前端頁面如下:
模板如下藐石,筆者放在了\static\model.docx路徑下:
在項目的位置如下即供,筆者是在Add.vue組件中引入的,相對模板路徑為../../static/word/template.docx 于微。
使用
我們可以參照 docxtemplater 給出的例子, 來實現(xiàn)文件導(dǎo)出逗嫡。
- 讀取模板文件內(nèi)容
- 裝載到zip對象中
- 設(shè)置文件數(shù)據(jù)
- 生成文件
- 保存文件
代碼如下:
// 點擊導(dǎo)出word
exportWord: function() {
let that = this;
// 讀取并獲得模板文件的二進(jìn)制內(nèi)容
JSZipUtils.getBinaryContent("../../static/model.docx", function(error, content) {
// model.docx是模板。我們在導(dǎo)出的時候株依,會根據(jù)此模板來導(dǎo)出對應(yīng)的數(shù)據(jù)
// 拋出異常
if (error) {
throw error;
}
// 創(chuàng)建一個PizZip實例驱证,內(nèi)容為模板的內(nèi)容
let zip = new PizZip(content);
// 創(chuàng)建并加載docxtemplater實例對象
let doc = new docxtemplater().loadZip(zip);
// 設(shè)置模板變量的值
doc.setData({
table: that.videoParam.data
});
try {
// 用模板變量的值替換所有模板變量
doc.render();
} catch (error) {
// 拋出異常
let e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties
};
console.log(JSON.stringify({ error: e }));
throw error;
}
// 生成一個代表docxtemplater對象的zip文件(不是一個真實的文件,而是在內(nèi)存中的表示)
let out = doc.getZip().generate({
type: "blob",
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
});
// 將目標(biāo)文件對象保存為目標(biāo)類型的文件恋腕,并命名
saveAs(out, "視頻參數(shù).docx");
});
}
最終下載的效果如下
注意
很多朋友都說遇到了以下問題抹锄,筆者當(dāng)時開發(fā)也遇到過,經(jīng)檢驗是以下兩個問題引入的荠藤,希望大家再檢查下相關(guān)路徑和配置伙单。
Can't find end of central directory : is this a zip file ?
- docxtemplater 不支持jszip,會有報錯哈肖,因此要使用PizZip
- 注意模板的路徑要寫正確吻育,不然會報錯找不到文件
總結(jié)
本文簡單的介紹了如何在前端使用已有的工具來實現(xiàn)前端導(dǎo)出word文檔淤井,希望對有類似需求的童鞋們有所幫助布疼。
參考文章: