import express from 'express' export const docxTemplateRoute = express.Router(); import {mimeToExtension,templateData} from './report-template' import fs from 'fs' import { createReport } from 'docx-templates'; import qrcode from 'yaqrcode' // แก้ package.json ของ LibreOfficeFileConverter // https://github.com/microsoft/TypeScript/issues/52363#issuecomment-1659179354 import { LibreOfficeFileConverter } from 'libreoffice-file-converter'; const TEMPLATE_FOLDER_NAME = "templates/docx" /** * docxTemplate Uses docx-template to convert input data and template to output buffer. * You have to handle exception throw by function * template keep in folder templates * @param {String} base base path of caller relate to template-docx foler (no trail slash) * @param {templateData} tdata Template Information in JSON format * @param {String} outputMediaType output extension * @return {Promise} output buffer after apply template. */ export async function docxTemplateX(base: string=".", tdata: templateData, outputMediaType: string="docx"): Promise { try { let template = await fs.promises.readFile(`${base}/${TEMPLATE_FOLDER_NAME}/${tdata.template}.docx`) const buffer = await createReport({ template, data: tdata.data, additionalJsContext: { qrCode: (contents: string, caption: string, size: number, width: number, height: number) => { const dataUrl = qrcode(contents, { size: size }); const data = dataUrl.slice('data:image/gif;base64,'.length); return { width, height, data, extension: '.gif', caption }; }, } }); if (outputMediaType === "docx") return buffer const libreOfficeFileConverter = new LibreOfficeFileConverter({ childProcessOptions: { timeout: 60 * 1000, }, }); const lbuffer = await libreOfficeFileConverter.convertBuffer(Buffer.from(buffer), outputMediaType); return lbuffer } catch (e) { throw (e) } } /** javascript-obfuscator:disable * @swagger * /api/v1/report-template/docx: * get: * summary: แสดงรายการ template ที่มีในโฟลเดอร์ templates * tags: [report-template] * responses: * 200: * description: array of template * content: * applicatin/json: * schema: * type: array * items: * type: string * example: ["hello"] * 500: * description: Server error */ docxTemplateRoute.get("/", async function (req, res) { try { const fileList = await fs.promises.readdir(`./${TEMPLATE_FOLDER_NAME}`) const templateList = fileList.map((f) => f.split('.docx')[0]) res.send(templateList) } catch (ex) { res.statusCode = 500; res.statusMessage = 'Internal Server Error'; res.end(res.statusMessage); console.error('Error during get template list: ', ex); } }) /** javascript-obfuscator:disable * @swagger * /api/v1/report-template/docx: * post: * summary: สร้างเอกสารโดยใช้ template จากไฟล์ docx จะแทนค่าตัวแปรในเอกสาร หรือจะแปลงเป็นฟอร์แม็ตอื่นได้ด้วยรองรับ docx pdf odt, ค่า template เป็นชื่อของ template, reportName เป็นชื่อไฟล์ที่ต้องการ * tags: [report-template] * requestBody: * required: true * content: * application/json: * schema: * $ref: '#/components/schemas/templateData' * example: * template: hello * reportName: docx-report * data: {"docNo":"๑๒๓๔๕","me": "กระผม","prefix": "นาย","name": "สรวิชญ์","surname": "พลสิทธิ์","position": "Chief Technology Officer","org": {"type": "บริษัท","name": "เฟรปเป้ที","url": "https://frappet.com"},"employees": [{"name": "ภาวิชญ์","surname": "พลสิทธิ์"},{"name": "วิชญาภา","surname": "พลสิทธิ์"}]} * responses: * 201: * description: เอกสารถูกสร้างขึ้น * content: * application/vnd.openxmlformats-officedocument.wordprocessingml.document: * schema: * type: string * format: binary * application/pdf: * schema: * type: string * format: binary * application/vnd.oasis.opendocument.text: * schema: * type: string * format: binary * image/png: * schema: * type: string * format: binary * image/jpeg: * schema: * type: string * format: binary * 500: * description: Server error * */ docxTemplateRoute.post("/", async function (req, res) { try { if (!req.headers['content-type'] || !req.headers['accept']) throw new Error("Require header content-type, accept") let inputType = mimeToExtension(req.headers['content-type']); let outputMediaType = mimeToExtension(req.headers['accept']); console.log('content-type: ', inputType); console.log('accept: ', outputMediaType); let buffer = await docxTemplateX('.', req.body, outputMediaType) res.statusCode = 201; res.setHeader('Content-Type', req.headers['accept']); res.setHeader('Content-Disposition', `attachment;filename=${req.body.reportName}.${outputMediaType}`); res.setHeader('Content-Length', buffer.length); res.end(buffer); } catch (ex) { res.statusCode = 500; res.statusMessage = 'Internal Server Error during get docx template list'; res.end(res.statusMessage); console.error('Error during apply template: ', ex); } })