Vue-純前端導(dǎo)出word文檔

在項目中,我們可以借助后端返回文件流實現(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)出的比較簡單,前端頁面如下:

image

模板如下藐石,筆者放在了\static\model.docx路徑下:

image

在項目的位置如下即供,筆者是在Add.vue組件中引入的,相對模板路徑為../../static/word/template.docx 于微。

image

使用

我們可以參照 docxtemplater 給出的例子, 來實現(xiàn)文件導(dǎo)出逗嫡。

  1. 讀取模板文件內(nèi)容
  2. 裝載到zip對象中
  3. 設(shè)置文件數(shù)據(jù)
  4. 生成文件
  5. 保存文件

代碼如下:

 // 點擊導(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");
    });
  }

最終下載的效果如下

image

注意

很多朋友都說遇到了以下問題抹锄,筆者當(dāng)時開發(fā)也遇到過,經(jīng)檢驗是以下兩個問題引入的荠藤,希望大家再檢查下相關(guān)路徑和配置伙单。

 Can't find end of central directory : is this a zip file ? 

  • docxtemplater 不支持jszip,會有報錯哈肖,因此要使用PizZip
  • 注意模板的路徑要寫正確吻育,不然會報錯找不到文件

這位同學(xué)也是因為路徑報上述錯誤,點擊查看

總結(jié)

本文簡單的介紹了如何在前端使用已有的工具來實現(xiàn)前端導(dǎo)出word文檔淤井,希望對有類似需求的童鞋們有所幫助布疼。

參考文章:

http://www.reibang.com/p/b3622d6f8d98

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市币狠,隨后出現(xiàn)的幾起案子缎除,更是在濱河造成了極大的恐慌,老刑警劉巖总寻,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件器罐,死亡現(xiàn)場離奇詭異,居然都是意外死亡渐行,警方通過查閱死者的電腦和手機(jī)轰坊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門铸董,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肴沫,你說我怎么就攤上這事粟害。” “怎么了颤芬?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵悲幅,是天一觀的道長。 經(jīng)常有香客問我站蝠,道長汰具,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任菱魔,我火速辦了婚禮留荔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘澜倦。我一直安慰自己聚蝶,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布藻治。 她就那樣靜靜地躺著碘勉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪桩卵。 梳的紋絲不亂的頭發(fā)上恰聘,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機(jī)與錄音吸占,去河邊找鬼晴叨。 笑死,一個胖子當(dāng)著我的面吹牛矾屯,可吹牛的內(nèi)容都是我干的兼蕊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼件蚕,長吁一口氣:“原來是場噩夢啊……” “哼孙技!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起排作,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤牵啦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后妄痪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哈雏,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了裳瘪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片土浸。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖彭羹,靈堂內(nèi)的尸體忽然破棺而出黄伊,到底是詐尸還是另有隱情,我是刑警寧澤派殷,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布还最,位于F島的核電站,受9級特大地震影響毡惜,放射性物質(zhì)發(fā)生泄漏拓轻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一虱黄、第九天 我趴在偏房一處隱蔽的房頂上張望悦即。 院中可真熱鬧吮成,春花似錦橱乱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至茶宵,卻和暖如春危纫,著一層夾襖步出監(jiān)牢的瞬間斯稳,已是汗流浹背铆铆。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留靡羡,地道東北人瞒大。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓螃征,卻偏偏與公主長得像,于是被迫代替她去往敵國和親透敌。 傳聞我的和親對象是個殘疾皇子盯滚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容