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)出的比較簡單,前端頁面如下:

前端

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

模板

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

注意引用路徑

使用

我們可以參照 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.png

注意

很多朋友都說遇到了以下問題彰导,筆者當(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閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件组哩,死亡現(xiàn)場離奇詭異等龙,居然都是意外死亡,警方通過查閱死者的電腦和手機伶贰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門蛛砰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人黍衙,你說我怎么就攤上這事泥畅。” “怎么了琅翻?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵位仁,是天一觀的道長。 經(jīng)常有香客問我方椎,道長聂抢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任辩尊,我火速辦了婚禮涛浙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己轿亮,他們只是感情好疮薇,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著我注,像睡著了一般按咒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上但骨,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天励七,我揣著相機與錄音,去河邊找鬼奔缠。 笑死掠抬,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的校哎。 我是一名探鬼主播两波,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼闷哆!你這毒婦竟也來了腰奋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤抱怔,失蹤者是張志新(化名)和其女友劉穎劣坊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體屈留,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡局冰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了灌危。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锐想。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖乍狐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情固逗,我是刑警寧澤浅蚪,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站烫罩,受9級特大地震影響惜傲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贝攒,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一盗誊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦哈踱、人聲如沸荒适。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刀诬。三九已至,卻和暖如春邪财,著一層夾襖步出監(jiān)牢的瞬間陕壹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工树埠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留糠馆,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓怎憋,卻偏偏與公主長得像又碌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子盛霎,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

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

  • 一赠橙、需要的js依賴 實現(xiàn)此功能需要使用到docxtemplater、jszip-utils愤炸、jszip期揪、FileS...
    GL曲終人散閱讀 40,298評論 47 16
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,089評論 1 32
  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運行的地址不確定 關(guān)于...
    SeanCST閱讀 7,779評論 0 27
  • feisky云計算规个、虛擬化與Linux技術(shù)筆記posts - 1014, comments - 298, trac...
    不排版閱讀 3,815評論 0 5
  • ORA-00001: 違反唯一約束條件 (.) 錯誤說明:當(dāng)在唯一索引所對應(yīng)的列上鍵入重復(fù)值時凤薛,會觸發(fā)此異常。 O...
    我想起個好名字閱讀 5,176評論 0 9