NodeJs之word文件生成與解析
一,介紹與需求
1.1,介紹
1,officegen 模塊可以為Microsoft Office 2007及更高版本生成Office Open XML文件。此模塊不依賴於任何框架,您不需要安裝Microsoft Office,因此您可以將它用於任何類型的 JavaScript 應用程序。輸出也是流而不是文件,不依賴於任何輸出工具。此模塊應適用於支持Node.js 0.10或更高版本的任何環境,包括Linux,OSX和Windows。
2,textract文本提取節點模塊。
3,pdf2json是一個節點。js模塊解析和轉換PDF從二進制到json格式,它是用PDF構建的。並通過瀏覽器外的交互式表單元素和文本內容解析對其進行擴展。其目標是在web服務中包裝時啟用帶有交互式表單元素的服務器端PDF解析,並在作為命令行實用程序使用時啟用將本地PDF解析為json文件。
1.2,需求
二,文件生成導出
第一步:安裝officegen
1 cnpm install officegen --save
第二步:引入officegen
1 var officegen = require('officegen'); 2 var fs = require('fs'); 3 var docx = officegen('docx');//word 4 var pptx = officegen('pptx');//pptx
第三步:使用officegen docx
1 ... 2 3 docx.on('finalize', function (written) { 4 console.log('Finish to create Word file.\nTotal bytes created: ' + written + '\n'); 5 }); 6 7 8 docx.on('error', function (err) { 9 console.log(err); 10 }); 11 12 ... 13 14 //var tows = ['id', 'provinceZh', 'leaderZh', 'cityZh', 'cityEn'];//創建一個和表頭對應且名稱與數據庫字段對應數據,便於循環取出數據 15 var pObj = docx.createP({ align: 'center' });// 創建行 設置居中 大標題 16 pObj.addText('全國所有城市', { bold: true, font_face: 'Arial', font_size: 18 });// 添加文字 設置字體樣式 加粗 大小 17 18 // let towsLen = tows.length 19 let dataLen = data.length 20 for (var i = 0; i < dataLen; i++) {//循環數據庫得到的數據,因為取出的數據格式為 21 //[{"id" : "101010100","provinceZh" : "北京","leaderZh" : "北京","cityZh" : "北京","cityEn" : "beijing"},{…………},{…………}] 22 /************************* 文本 *******************************/ 23 // var pObj = docx.createP();//創建一行 24 // pObj.addText(`(${i+1}), `,{ bold: true, font_face: 'Arial',}); 25 // pObj.addText(`省級:`,{ bold: true, font_face: 'Arial',}); 26 // pObj.addText(`${data[i]['provinceZh']} `,); 27 // pObj.addText(`市級:`,{ bold: true, font_face: 'Arial',}); 28 // pObj.addText(`${data[i]['leaderZh']} `); 29 // pObj.addText(`縣區:`,{ bold: true, font_face: 'Arial',}); 30 // pObj.addText(`${data[i]['cityZh']}`); 31 32 /************************* 表格 *******************************/ 33 let SingleRow = [data[i]['id'], data[i]['provinceZh'], data[i]['leaderZh'], data[i]['cityZh']] 34 table.push(SingleRow) 35 } 36 docx.createTable(table, tableStyle); 37 var out = fs.createWriteStream('out.docx');// 文件寫入 38 out.on('error', function (err) { 39 console.log(err); 40 }); 41 var result = docx.generate(out);// 服務端生成word 42 res.writeHead(200, { 43 // 注意這里的type設置,導出不同文件type值不同application/vnd.openxmlformats-officedocument.wordprocessingml.document 44 "Content-Type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", 45 'Content-disposition': 'attachment; filename=out' + moment(new Date().getTime()).format('YYYYMMDDhhmmss') + '.docx' 46 }); 47 docx.generate(res);// 客戶端導出word
第四步:拋出接口
1 router.put('/download/word', function (req, res) { 2 console.log('exportWord-------------'); 3 docx.on('finalize', function (written) { 4 console.log('Finish to create Word file.\nTotal bytes created: ' + written + '\n'); 5 }); 6 7 8 docx.on('error', function (err) { 9 console.log(err); 10 }); 11 let fields = { 12 id: '', 13 provinceZh: '', 14 leaderZh: '', 15 cityZh: '', 16 cityEn: '' 17 } 18 var table = [ 19 [{ 20 val: "No.", 21 opts: { 22 align: "center", 23 vAlign: "center", 24 sz: '36', 25 // cellColWidth: 42, 26 // b:true, 27 // sz: '48', 28 // shd: { 29 // fill: "7F7F7F", 30 // themeFill: "text1", 31 // "themeFillTint": "80" 32 // }, 33 // fontFamily: "Avenir Book" 34 } 35 }, { 36 val: "省份", 37 opts: { 38 align: "center", 39 vAlign: "center", 40 sz: '36', 41 // b:true, 42 // color: "A00000", 43 // align: "right", 44 // shd: { 45 // fill: "92CDDC", 46 // themeFill: "text1", 47 // "themeFillTint": "80" 48 // } 49 } 50 }, { 51 val: "市", 52 opts: { 53 align: "center", 54 vAlign: "center", 55 sz: '36', 56 // cellColWidth: 42, 57 // b:true, 58 // sz: '48', 59 // shd: { 60 // fill: "92CDDC", 61 // themeFill: "text1", 62 // "themeFillTint": "80" 63 // } 64 } 65 }, { 66 val: "區/縣", 67 opts: { 68 align: "center", 69 vAlign: "center", 70 sz: '36', 71 // cellColWidth: 42, 72 // b:true, 73 // sz: '48', 74 // shd: { 75 // fill: "92CDDC", 76 // themeFill: "text1", 77 // "themeFillTint": "80" 78 // } 79 } 80 }], 81 ] 82 83 var tableStyle = { 84 tableColWidth: 2400, 85 tableSize: 24, 86 tableColor: "ada", 87 tableAlign: "center", 88 tableVAlign: "center", 89 tableFontFamily: "Comic Sans MS", 90 borders: true 91 } 92 93 MongoDbAction.getFieldsByConditions('AllCity', {}, fields, function (err, data) {//根據需求查詢想要的字段 94 if (err) { 95 //執行出錯 96 } else { 97 //var tows = ['id', 'provinceZh', 'leaderZh', 'cityZh', 'cityEn'];//創建一個和表頭對應且名稱與數據庫字段對應數據,便於循環取出數據 98 var pObj = docx.createP({ align: 'center' });// 創建行 設置居中 大標題 99 pObj.addText('全國所有城市', { bold: true, font_face: 'Arial', font_size: 18 });// 添加文字 設置字體樣式 加粗 大小 100 101 // let towsLen = tows.length 102 let dataLen = data.length 103 for (var i = 0; i < dataLen; i++) {//循環數據庫得到的數據,因為取出的數據格式為 104 //[{"id" : "101010100","provinceZh" : "北京","leaderZh" : "北京","cityZh" : "北京","cityEn" : "beijing"},{…………},{…………}] 105 /************************* 文本 *******************************/ 106 // var pObj = docx.createP();//創建一行 107 // pObj.addText(`(${i+1}), `,{ bold: true, font_face: 'Arial',}); 108 // pObj.addText(`省級:`,{ bold: true, font_face: 'Arial',}); 109 // pObj.addText(`${data[i]['provinceZh']} `,); 110 // pObj.addText(`市級:`,{ bold: true, font_face: 'Arial',}); 111 // pObj.addText(`${data[i]['leaderZh']} `); 112 // pObj.addText(`縣區:`,{ bold: true, font_face: 'Arial',}); 113 // pObj.addText(`${data[i]['cityZh']}`); 114 115 /************************* 表格 *******************************/ 116 let SingleRow = [data[i]['id'], data[i]['provinceZh'], data[i]['leaderZh'], data[i]['cityZh']] 117 table.push(SingleRow) 118 } 119 docx.createTable(table, tableStyle); 120 var out = fs.createWriteStream('out.docx');// 文件寫入 121 out.on('error', function (err) { 122 console.log(err); 123 }); 124 var result = docx.generate(out);// 服務端生成word 125 res.writeHead(200, { 126 // 注意這里的type設置,導出不同文件type值不同application/vnd.openxmlformats-officedocument.wordprocessingml.document 127 "Content-Type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", 128 'Content-disposition': 'attachment; filename=out' + moment(new Date().getTime()).format('YYYYMMDDhhmmss') + '.docx' 129 }); 130 docx.generate(res);// 客戶端導出word 131 } 132 }); 133 134 });
第五步:前端調用
下載調用方法
1 downloadWordOper() { 2 // var url = "http://localhost:8880/api/v1/yingqi/download/word"; 3 // window.location = url;//這里不能使用get方法跳轉,否則下載不成功 4 this.$http(downloadWord()).then((res)=>{ 5 //這里res.data是返回的blob對象 6 var blob = new Blob([res.data], {type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=utf-8'}); //application/vnd.openxmlformats-officedocument.wordprocessingml.document這里表示doc類型 7 downloadFile(blob,'word','docx') 8 }) 9 10 },
downloadFile方法代碼如下:
1 /** 2 *下載文件 3 * @param blob :返回數據的blob對象 4 * @param tagFileName :下載后文件名標記 5 * @param fileType :文件類 word(docx) excel(xlsx) ppt等 6 */ 7 export function downloadFile(blob,tagFileName,fileType) { 8 var downloadElement = document.createElement('a'); 9 var href = window.URL.createObjectURL(blob); //創建下載的鏈接 10 downloadElement.href = href; 11 downloadElement.download = tagFileName+moment(new Date().getTime()).format('YYYYMMDDhhmmss')+'.'+fileType; //下載后文件名 12 document.body.appendChild(downloadElement); 13 downloadElement.click(); //點擊下載 14 document.body.removeChild(downloadElement); //下載完成移除元素 15 window.URL.revokeObjectURL(href); //釋放掉blob對象 16 }

第六步:下載后的效果

ppt生成下載類似,只是設置的writeHead類型與使用的方法不一樣
1 router.put('/download/createPpt', function (req, res) { 2 console.log('exportPpt-------------'); 3 pptx.on('finalize', function (written) { 4 console.log('Finish to create ppt file.\nTotal bytes created: ' + written + '\n'); 5 }); 6 7 8 pptx.on('error', function (err) { 9 console.log(err); 10 }); 11 12 let slide1 = pptx.makeNewSlide();//創建一個新幻燈片 13 slide1.title = 'PPT文件'; 14 slide1.addText('Office generator', { 15 y: 66, x: 'c', cx: '50%', cy: 60, font_size: 48, 16 color: '0000ff' 17 }); 18 19 slide1.addText('Big Red', { 20 y: 250, x: 10, cx: '70%', 21 font_face: 'Wide Latin', font_size: 54, 22 color: 'cc0000', bold: true, underline: true 23 }); 24 25 var out = fs.createWriteStream('out.pptx');// 文件寫入 26 out.on('error', function (err) { 27 console.log('error2===',err); 28 }); 29 var result = pptx.generate(out);// 服務端生成ppt 30 res.writeHead(200, { 31 // 注意這里的type設置,導出不同文件type值不同application/vnd.openxmlformats-officedocument.presentationml.presentation 32 // "Content-Type": "application/vnd.openxmlformats-officedocument.presentationml.presentation", 33 // 'Content-disposition': 'attachment; filename=out' + moment(new Date().getTime()).format('YYYYMMDDhhmmss') + '.pptx' 34 "Content-Type": "application/vnd.openxmlformats-officedocument.presentationml.presentation", 35 'Content-disposition': 'attachment; filename=surprise.pptx' 36 }); 37 pptx.generate(res);// 客戶端導出ppt 38 39 });
三,文件上傳解析
3.1,word文檔解析
第一步:安裝textract
1 cnpm install textract --save
第二步:引入textract
1 //引入textract解析word模塊 2 var textract = require('textract');//對於docx文件,您可以使用textract,它將從.docx文件中提取文本。 3 var fs = require('fs');
第三步:解析文檔
1 function parseWord(excelConfig, res) { 2 textract.fromFileWithPath(excelConfig.excel_Dir, function (error, text) { 3 if (error) { 4 res.status(200).json({ 5 httpCode: 200, 6 message: '導入解析失敗', 7 data: error, 8 returnValue: 0 9 }); 10 } else { 11 res.status(200).json({ 12 httpCode: 200, 13 message: '導入成功', 14 data: { 15 result: text 16 }, 17 returnValue: 1 18 }); 19 } 20 }) 21 }
第四步:解析后刪除文檔
1 fs.unlink(excelConfig.excel_Dir, function (err) { 2 if (err) throw err; 3 console.log("刪除文件" + excelConfig.excel_Dir + "成功") 4 })
第五步:拋出接口調用后的效果

3.2,pdf文檔解析
第一步:安裝pdf2json
1 cnpm install pdf2json --save
第二步:引入pdf2json
1 var PDFParser = require("pdf2json"); 2 var fs = require('fs');
第三步:解析文檔
1 function parsePdf(excelConfig, res) { 2 var pdfParser = new PDFParser(this, 1); 3 pdfParser.loadPDF(excelConfig.excel_Dir); 4 pdfParser.on("pdfParser_dataError", errData => { 5 res.status(200).json({ 6 httpCode: 200, 7 message: '導入解析失敗', 8 data: errData, 9 returnValue: 0 10 }); 11 }); 12 pdfParser.on("pdfParser_dataReady", pdfData => { 13 let data = pdfParser.getRawTextContent() 14 fs.writeFile('./uploads/test.txt', data, function (err) { 15 if (err) { 16 throw err; 17 } 18 }); 19 res.status(200).json({ 20 httpCode: 200, 21 message: '導入成功', 22 data: { 23 result: data 24 }, 25 returnValue: 1 26 }); 27 }); 28 }
第四步:解析后刪除文檔
1 fs.unlink(excelConfig.excel_Dir, function (err) { 2 if (err) throw err; 3 console.log("刪除文件" + excelConfig.excel_Dir + "成功") 4 })
第五步:拋出接口調用后的效果

