在項目中亮钦,我們可以借助后端返回文件流實現(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文檔,希望對有類似需求的童鞋們有所幫助损同。
參考文章: