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 })
第五步:抛出接口调用后的效果