api upload template
This commit is contained in:
parent
ba8175204c
commit
58f8e928a0
6 changed files with 3742 additions and 3104 deletions
|
|
@ -1,18 +1,18 @@
|
|||
import express from "express"
|
||||
export const docxTemplateRoute = express.Router()
|
||||
|
||||
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'
|
||||
import { mimeToExtension, templateData } from "./report-template"
|
||||
import fs from "fs"
|
||||
import { createReport } from "docx-templates"
|
||||
const qrcode = require("yaqrcode")
|
||||
const axios = require("axios")
|
||||
// แก้ package.json ของ LibreOfficeFileConverter
|
||||
// https://github.com/microsoft/TypeScript/issues/52363#issuecomment-1659179354
|
||||
import { LibreOfficeFileConverter } from 'libreoffice-file-converter';
|
||||
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.
|
||||
* 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)
|
||||
|
|
@ -20,34 +20,44 @@ const TEMPLATE_FOLDER_NAME = "templates/docx"
|
|||
* @param {String} outputMediaType output extension
|
||||
* @return {Promise<Uint8Array>} output buffer after apply template.
|
||||
*/
|
||||
export async function docxTemplateX(base: string=".", tdata: templateData, outputMediaType: string="docx"): Promise<Uint8Array> {
|
||||
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)
|
||||
}
|
||||
export async function docxTemplateX(template: Buffer, tdata: templateData, outputMediaType: string = "docx"): Promise<Uint8Array> {
|
||||
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 }
|
||||
},
|
||||
addImageByUrl: async (imageUrl: string, width: number, height: number, caption: string) => {
|
||||
const response = await axios.get(imageUrl, { responseType: "arraybuffer" })
|
||||
const imageData = Buffer.from(response.data).toString("base64") // Convert image to base64
|
||||
const ext = ".png" // Assuming PNG format; adjust based on actual image type
|
||||
|
||||
return {
|
||||
width,
|
||||
height,
|
||||
data: imageData,
|
||||
extension: ext,
|
||||
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
|
||||
|
|
@ -63,32 +73,39 @@ export async function docxTemplateX(base: string=".", tdata: templateData, outpu
|
|||
* applicatin/json:
|
||||
* schema:
|
||||
* type: array
|
||||
* items:
|
||||
* 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);
|
||||
}
|
||||
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]
|
||||
* parameters:
|
||||
* - name: folder
|
||||
* in: query
|
||||
* description: ชื่อโฟลเดอร์
|
||||
* required: false
|
||||
* schema:
|
||||
* type: string
|
||||
* example: test
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
|
|
@ -128,26 +145,175 @@ docxTemplateRoute.get("/", async function (req, res) {
|
|||
*
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
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 template = null
|
||||
// Save the converted file to disk
|
||||
if (req.query["folder"]) {
|
||||
template = await fs.promises.readFile(`./${TEMPLATE_FOLDER_NAME}/${req.query["folder"]}/${req.body.template}.docx`)
|
||||
} else {
|
||||
template = await fs.promises.readFile(`./${TEMPLATE_FOLDER_NAME}/${req.body.template}.docx`)
|
||||
}
|
||||
let buffer = await docxTemplateX(template, 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)
|
||||
}
|
||||
})
|
||||
|
||||
/** javascript-obfuscator:disable
|
||||
* @swagger
|
||||
* /api/v1/report-template/docx/upload:
|
||||
* post:
|
||||
* summary: อัพไฟล์ docx
|
||||
* tags: [report-template]
|
||||
* parameters:
|
||||
* - name: report_name
|
||||
* in: query
|
||||
* description: ชื่อไฟล์
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* example: report
|
||||
* - name: folder
|
||||
* in: query
|
||||
* description: ชื่อโฟลเดอร์
|
||||
* required: false
|
||||
* schema:
|
||||
* type: string
|
||||
* example: test
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/octet-stream:
|
||||
* schema:
|
||||
* type: string
|
||||
* format: binary
|
||||
* responses:
|
||||
* 201:
|
||||
* description: file was converted.
|
||||
* content:
|
||||
* application/octet-stream:
|
||||
* schema:
|
||||
* type: string
|
||||
* format: binary
|
||||
* application/msword:
|
||||
* schema:
|
||||
* type: string
|
||||
* format: binary
|
||||
* 400:
|
||||
* description: Invalid format
|
||||
* 500:
|
||||
* description: Server error
|
||||
*
|
||||
*/
|
||||
docxTemplateRoute.post("/upload", async function (req, res) {
|
||||
try {
|
||||
if (!req.headers["content-type"] || !req.headers["accept"] || !req.query["report_name"] || req.headers["content-type"] !== "application/octet-stream") {
|
||||
res.statusCode = 400
|
||||
res.statusMessage = "Require header: content-type(application/octet-stream) accept"
|
||||
res.end(res.statusMessage)
|
||||
console.log(req.headers["content-type"], req.headers["accept"], req.query["report_name"])
|
||||
return
|
||||
}
|
||||
// Determine the output media type and report name from headers
|
||||
let outputMediaType = mimeToExtension(req.headers["accept"])
|
||||
let reportName = req.query["report_name"]
|
||||
console.log("convert output: " + outputMediaType)
|
||||
|
||||
// Save the converted file to disk
|
||||
if (req.query["folder"]) {
|
||||
// Ensure the template folder exists
|
||||
await fs.promises.mkdir(`TEMPLATE_FOLDER_NAME/${req.query["folder"]}`, { recursive: true })
|
||||
await fs.promises.writeFile(`./${TEMPLATE_FOLDER_NAME}/${req.query["folder"]}/${reportName}.docx`, req.body)
|
||||
} else {
|
||||
// Ensure the template folder exists
|
||||
await fs.promises.mkdir(TEMPLATE_FOLDER_NAME, { recursive: true })
|
||||
await fs.promises.writeFile(`./${TEMPLATE_FOLDER_NAME}/${reportName}.docx`, req.body)
|
||||
}
|
||||
|
||||
// Send a response to the client
|
||||
res.statusCode = 201
|
||||
res.json({ message: "File converted and saved successfully" })
|
||||
} catch (ex) {
|
||||
res.statusCode = 500
|
||||
res.statusMessage = "Internal Server Error"
|
||||
res.end(res.statusMessage)
|
||||
console.error(`Error during convert with soffice:`, ex)
|
||||
}
|
||||
})
|
||||
|
||||
/** javascript-obfuscator:disable
|
||||
* @swagger
|
||||
* /api/v1/report-template/docx/download:
|
||||
* post:
|
||||
* summary: โหลดไฟล์ docx
|
||||
* tags: [report-template]
|
||||
* parameters:
|
||||
* - name: folder
|
||||
* in: query
|
||||
* description: ชื่อโฟลเดอร์
|
||||
* required: false
|
||||
* schema:
|
||||
* type: string
|
||||
* example: test
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/templateData'
|
||||
* example:
|
||||
* template: docx-report
|
||||
* responses:
|
||||
* 201:
|
||||
* description: เอกสารถูกสร้างขึ้น
|
||||
* content:
|
||||
* application/vnd.openxmlformats-officedocument.wordprocessingml.document:
|
||||
* schema:
|
||||
* type: string
|
||||
* format: binary
|
||||
* application/vnd.oasis.opendocument.text:
|
||||
* schema:
|
||||
* type: string
|
||||
* format: binary
|
||||
* 500:
|
||||
* description: Server error
|
||||
*
|
||||
*/
|
||||
docxTemplateRoute.post("/download", async function (req, res) {
|
||||
try {
|
||||
if (!req.headers["content-type"] || !req.headers["accept"] || !req.body.template) 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 = null
|
||||
if (req.query["folder"]) {
|
||||
buffer = await fs.promises.readFile(`./${TEMPLATE_FOLDER_NAME}/${req.query["folder"]}/${req.body.template}.docx`)
|
||||
} else {
|
||||
buffer = await fs.promises.readFile(`./${TEMPLATE_FOLDER_NAME}/${req.body.template}.docx`)
|
||||
}
|
||||
res.statusCode = 201
|
||||
res.setHeader("Content-Type", req.headers["accept"])
|
||||
res.setHeader("Content-Disposition", `attachment;filename=${req.body.template}.${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)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,48 +1,46 @@
|
|||
export interface templateData {
|
||||
template: string;
|
||||
reportName: string;
|
||||
data: object
|
||||
template: string
|
||||
reportName: string
|
||||
data: object
|
||||
}
|
||||
export interface IDictionary<TValue> {
|
||||
[key: string]: TValue;
|
||||
[key: string]: TValue
|
||||
}
|
||||
export function mimeToExtension(mime: string): string {
|
||||
const mimeList: IDictionary<string> = {
|
||||
"application/pdf": "pdf",
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
|
||||
"application/msword": "doc",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
|
||||
"application/vnd.ms-excel": "xls",
|
||||
"application/vnd.ms-powerpoint": "ppt",
|
||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
|
||||
"application/vnd.oasis.opendocument.text": "odt",
|
||||
"application/vnd.oasis.opendocument.spreadsheet":"ods",
|
||||
"application/vnd.oasis.opendocument.presentation":"odp",
|
||||
"text/html": "html",
|
||||
"application/json": "json",
|
||||
"text/csv": "csv",
|
||||
"text/markdown": "md",
|
||||
"text/plain": "txt",
|
||||
"application/rtf": "rtf",
|
||||
"image/png": "png",
|
||||
"image/jpeg": "jpeg",
|
||||
}
|
||||
if (mimeList[mime]) {
|
||||
return mimeList[mime]
|
||||
} else if (mime.match(/^application\/x\./)) {
|
||||
return mime.substr(mime.indexOf('.') + 1);
|
||||
} else {
|
||||
return mime
|
||||
}
|
||||
|
||||
const mimeList: IDictionary<string> = {
|
||||
"application/pdf": "pdf",
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
|
||||
"application/msword": "doc",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
|
||||
"application/vnd.ms-excel": "xls",
|
||||
"application/vnd.ms-powerpoint": "ppt",
|
||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
|
||||
"application/vnd.oasis.opendocument.text": "odt",
|
||||
"application/vnd.oasis.opendocument.spreadsheet": "ods",
|
||||
"application/vnd.oasis.opendocument.presentation": "odp",
|
||||
"text/html": "html",
|
||||
"application/json": "json",
|
||||
"text/csv": "csv",
|
||||
"text/markdown": "md",
|
||||
"text/plain": "txt",
|
||||
"application/rtf": "rtf",
|
||||
"image/png": "png",
|
||||
"image/jpeg": "jpeg",
|
||||
}
|
||||
if (mimeList[mime]) {
|
||||
return mimeList[mime]
|
||||
} else if (mime.match(/^application\/x\./)) {
|
||||
return mime.substr(mime.indexOf(".") + 1)
|
||||
} else {
|
||||
return mime
|
||||
}
|
||||
}
|
||||
/** javascript-obfuscator:disable
|
||||
* @swagger
|
||||
* tags:
|
||||
* name: report-template
|
||||
* description: API สำหรับสร้างเอกสารจาก Template docx หรือ xlsx การทำงานคล้ายการทำ Mail Merge ทำให้ยูสเซอร์ทั่วไปแก้ Template ได้ง่าย สามารถแปลงไฟล์นามสกุลอื่นๆที่ soffice รองรับ
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
/** javascript-obfuscator:disable
|
||||
* @swagger
|
||||
|
|
@ -66,4 +64,3 @@ export function mimeToExtension(mime: string): string {
|
|||
* type: object
|
||||
* description: value for template
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,93 +1,51 @@
|
|||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "Report Server",
|
||||
"version": "0.8.1",
|
||||
"description": "Technical preview releases - Report Server <br/>Advance create and convert document API for microservice era. ",
|
||||
"license": {
|
||||
"name": "by oom@Frappet",
|
||||
"url": "https://frappet.com"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://report-server.frappet.synology.me"
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "Report Server",
|
||||
"version": "0.8.1",
|
||||
"description": "Technical preview releases - Report Server <br/>Advance create and convert document API for microservice era. ",
|
||||
"license": {
|
||||
"name": "by oom@Frappet",
|
||||
"url": "https://frappet.com"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "https://bma-ehr.frappet.synology.me/"
|
||||
},
|
||||
{
|
||||
"url": "http://localhost:3000"
|
||||
},
|
||||
{
|
||||
"url": "http://192.168.2.101:3001"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/api/v1/report-template/convert": {
|
||||
"post": {
|
||||
"summary": "แปลงฟอร์แม็ตเอกสารเช่นจาก docx เป็น pdf ให้ตั้งค่า Media type เป็นชนิดไฟล์ที่ต้องการ",
|
||||
"tags": [
|
||||
"office-convert"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "report-name",
|
||||
"in": "header",
|
||||
"description": "ชื่อไฟล์ที่ต้องการหลังแปลง",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "report"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/octet-stream": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://report-server.frappet.synology.me"
|
||||
},
|
||||
{
|
||||
"url": "https://bma-ehr.frappet.synology.me/"
|
||||
},
|
||||
{
|
||||
"url": "http://localhost:3000"
|
||||
},
|
||||
{
|
||||
"url": "http://192.168.2.101:3001"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/api/v1/report-template/convert": {
|
||||
"post": {
|
||||
"summary": "แปลงฟอร์แม็ตเอกสารเช่นจาก docx เป็น pdf ให้ตั้งค่า Media type เป็นชนิดไฟล์ที่ต้องการ",
|
||||
"tags": [
|
||||
"office-convert"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "report-name",
|
||||
"in": "header",
|
||||
"description": "ชื่อไฟล์ที่ต้องการหลังแปลง",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
"example": "report"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "file was converted.",
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/pdf": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"application/vnd.oasis.opendocument.text": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"application/msword": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"image/png": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"image/jpeg": {
|
||||
"application/octet-stream": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
|
|
@ -95,242 +53,474 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid format"
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/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"
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "file was converted.",
|
||||
"content": {
|
||||
"application/pdf": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"example": [
|
||||
"hello"
|
||||
]
|
||||
"application/vnd.oasis.opendocument.text": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"application/msword": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"image/png": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"image/jpeg": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid format"
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error"
|
||||
}
|
||||
}
|
||||
},
|
||||
"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": "พลสิทธิ์"
|
||||
"/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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "เอกสารถูกสร้างขึ้น",
|
||||
"post": {
|
||||
"summary": "สร้างเอกสารโดยใช้ template จากไฟล์ docx จะแทนค่าตัวแปรในเอกสาร หรือจะแปลงเป็นฟอร์แม็ตอื่นได้ด้วยรองรับ docx pdf odt, ค่า template เป็นชื่อของ template, reportName เป็นชื่อไฟล์ที่ต้องการ",
|
||||
"tags": [
|
||||
"report-template"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "folder",
|
||||
"in": "query",
|
||||
"description": "ชื่อโฟลเดอร์",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "test"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": {
|
||||
"application/json": {
|
||||
"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"
|
||||
"$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": "พลสิทธิ์"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/report-template/xlsx": {
|
||||
"get": {
|
||||
"summary": "แสดงรายการ xlsx template",
|
||||
"tags": [
|
||||
"report-template"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "array of template",
|
||||
"content": {
|
||||
"applicatin/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "เอกสารถูกสร้างขึ้น",
|
||||
"content": {
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"example": [
|
||||
"hello"
|
||||
]
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error"
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"summary": "สร้างเอกสารจาก xlsx template แล้วส่งกลับมาเป็น xlsx pdf odt , ค่า template เป็นชื่อของ template ที่ใช้งาน, reportName เป็นชื่อไฟล์ที่ต้องการ",
|
||||
"tags": [
|
||||
"report-template"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"/api/v1/report-template/docx/upload": {
|
||||
"post": {
|
||||
"summary": "อัพไฟล์ docx",
|
||||
"tags": [
|
||||
"report-template"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "report_name",
|
||||
"in": "query",
|
||||
"description": "ชื่อไฟล์",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/templateData"
|
||||
},
|
||||
"example": {
|
||||
"template": "hello",
|
||||
"reportName": "xlsx-report",
|
||||
"data": {
|
||||
"docNo": "๑๒๓๔๕",
|
||||
"me": "กระผม",
|
||||
"prefix": "นาย",
|
||||
"name": "สรวิชญ์",
|
||||
"surname": "พลสิทธิ์",
|
||||
"position": "Chief Technology Officer",
|
||||
"org": {
|
||||
"type": "บริษัท",
|
||||
"name": "เฟรปเป้ที",
|
||||
"url": "https://frappet.com"
|
||||
},
|
||||
"employees": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "ภาวิชญ์",
|
||||
"surname": "พลสิทธิ์",
|
||||
"score": 80
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "วิชญาภา",
|
||||
"surname": "พลสิทธิ์",
|
||||
"score": 50
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "ฐิตาภา",
|
||||
"surname": "พลสิทธิ์",
|
||||
"score": 90
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "สรวิชญ์ พลสิทธิ์",
|
||||
"surname": "พลสิทธิ์",
|
||||
"score": 99
|
||||
"type": "string",
|
||||
"example": "report"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "folder",
|
||||
"in": "query",
|
||||
"description": "ชื่อโฟลเดอร์",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "test"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/octet-stream": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "file was converted.",
|
||||
"content": {
|
||||
"application/octet-stream": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"application/msword": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid format"
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/report-template/docx/download": {
|
||||
"post": {
|
||||
"summary": "โหลดไฟล์ docx",
|
||||
"tags": [
|
||||
"report-template"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "folder",
|
||||
"in": "query",
|
||||
"description": "ชื่อโฟลเดอร์",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "test"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/templateData"
|
||||
},
|
||||
"example": {
|
||||
"template": "docx-report"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "เอกสารถูกสร้างขึ้น",
|
||||
"content": {
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"application/vnd.oasis.opendocument.text": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/report-template/xlsx": {
|
||||
"get": {
|
||||
"summary": "แสดงรายการ xlsx template",
|
||||
"tags": [
|
||||
"report-template"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "array of template",
|
||||
"content": {
|
||||
"applicatin/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"example": [
|
||||
"hello"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error"
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "เอกสารถูกสร้างขึ้น created.",
|
||||
"post": {
|
||||
"summary": "สร้างเอกสารจาก xlsx template แล้วส่งกลับมาเป็น xlsx pdf odt , ค่า template เป็นชื่อของ template ที่ใช้งาน, reportName เป็นชื่อไฟล์ที่ต้องการ",
|
||||
"tags": [
|
||||
"report-template"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "folder",
|
||||
"in": "query",
|
||||
"description": "ชื่อโฟลเดอร์",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "test"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
"$ref": "#/components/schemas/templateData"
|
||||
},
|
||||
"example": {
|
||||
"template": "hello",
|
||||
"reportName": "xlsx-report",
|
||||
"data": {
|
||||
"docNo": "๑๒๓๔๕",
|
||||
"me": "กระผม",
|
||||
"prefix": "นาย",
|
||||
"name": "สรวิชญ์",
|
||||
"surname": "พลสิทธิ์",
|
||||
"position": "Chief Technology Officer",
|
||||
"org": {
|
||||
"type": "บริษัท",
|
||||
"name": "เฟรปเป้ที",
|
||||
"url": "https://frappet.com"
|
||||
},
|
||||
"employees": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "ภาวิชญ์",
|
||||
"surname": "พลสิทธิ์",
|
||||
"score": 80
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "วิชญาภา",
|
||||
"surname": "พลสิทธิ์",
|
||||
"score": 50
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "ฐิตาภา",
|
||||
"surname": "พลสิทธิ์",
|
||||
"score": 90
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "สรวิชญ์ พลสิทธิ์",
|
||||
"surname": "พลสิทธิ์",
|
||||
"score": 99
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"application/pdf": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "เอกสารถูกสร้างขึ้น created.",
|
||||
"content": {
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"application/pdf": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"application/vnd.oasis.opendocument.spreadsheet": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"image/png": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"image/jpeg": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
},
|
||||
"application/vnd.oasis.opendocument.spreadsheet": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"image/png": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
},
|
||||
"image/jpeg": {
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/report-template/xlsx/upload": {
|
||||
"post": {
|
||||
"summary": "อัพไฟล์ xlsx",
|
||||
"tags": [
|
||||
"report-template"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "report_name",
|
||||
"in": "query",
|
||||
"description": "ชื่อไฟล์",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "report"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "folder",
|
||||
"in": "query",
|
||||
"description": "ชื่อโฟลเดอร์",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "test"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/octet-stream": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
|
|
@ -338,48 +528,112 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error"
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "file was converted.",
|
||||
"content": {
|
||||
"application/octet-stream": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid format"
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/report-template/xlsx/download": {
|
||||
"post": {
|
||||
"summary": "โหลดไฟล์ xlsx",
|
||||
"tags": [
|
||||
"report-template"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "folder",
|
||||
"in": "query",
|
||||
"description": "ชื่อโฟลเดอร์",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "test"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/templateData"
|
||||
},
|
||||
"example": {
|
||||
"template": "xlsx-report"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "เอกสารถูกสร้างขึ้น",
|
||||
"content": {
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"templateData": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"template",
|
||||
"reportName",
|
||||
"data",
|
||||
"finished"
|
||||
],
|
||||
"properties": {
|
||||
"template": {
|
||||
"type": "string",
|
||||
"description": "name of template"
|
||||
},
|
||||
"reportName": {
|
||||
"type": "string",
|
||||
"description": "name of report for download"
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"description": "value for template"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "office-convert",
|
||||
"description": "ใช้แปลงไฟล์จากเอกสารที่ libreoffice แปลงได้ เช่น docx เป็น pdf"
|
||||
},
|
||||
{
|
||||
"name": "report-template",
|
||||
"description": "API สำหรับสร้างเอกสารจาก Template docx หรือ xlsx การทำงานคล้ายการทำ Mail Merge ทำให้ยูสเซอร์ทั่วไปแก้ Template ได้ง่าย สามารถแปลงไฟล์นามสกุลอื่นๆที่ soffice รองรับ"
|
||||
}
|
||||
]
|
||||
}
|
||||
"components": {
|
||||
"schemas": {
|
||||
"templateData": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"template",
|
||||
"reportName",
|
||||
"data",
|
||||
"finished"
|
||||
],
|
||||
"properties": {
|
||||
"template": {
|
||||
"type": "string",
|
||||
"description": "name of template"
|
||||
},
|
||||
"reportName": {
|
||||
"type": "string",
|
||||
"description": "name of report for download"
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"description": "value for template"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "office-convert",
|
||||
"description": "ใช้แปลงไฟล์จากเอกสารที่ libreoffice แปลงได้ เช่น docx เป็น pdf"
|
||||
},
|
||||
{
|
||||
"name": "report-template",
|
||||
"description": "API สำหรับสร้างเอกสารจาก Template docx หรือ xlsx การทำงานคล้ายการทำ Mail Merge ทำให้ยูสเซอร์ทั่วไปแก้ Template ได้ง่าย สามารถแปลงไฟล์นามสกุลอื่นๆที่ soffice รองรับ"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import express from 'express'
|
||||
export const xlsxTemplateRoute = express.Router();
|
||||
import express from "express"
|
||||
export const xlsxTemplateRoute = express.Router()
|
||||
|
||||
import {mimeToExtension,templateData} from './report-template'
|
||||
import { ExcelTemplate } from 'xlsx-template-next'
|
||||
import fs from 'fs'
|
||||
import { LibreOfficeFileConverter } from 'libreoffice-file-converter';
|
||||
import { mimeToExtension, templateData } from "./report-template"
|
||||
import { ExcelTemplate } from "xlsx-template-next"
|
||||
import fs from "fs"
|
||||
import { LibreOfficeFileConverter } from "libreoffice-file-converter"
|
||||
const TEMPLATE_FOLDER_NAME = "templates/xlsx"
|
||||
|
||||
/**
|
||||
* xlsxTemplate Uses xlsx-template-next to convert input data and template to output buffer.
|
||||
* xlsxTemplate Uses xlsx-template-next 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)
|
||||
|
|
@ -17,30 +17,27 @@ const TEMPLATE_FOLDER_NAME = "templates/xlsx"
|
|||
* @param {Number} tab tab page of spread sheet , default = 1
|
||||
* @return {Promise<Uint8Array>} output buffer after apply template.
|
||||
*/
|
||||
export async function xlsxTemplateX(base: string=".", tdata: templateData, outputMediaType: string="xlsx",tab:number=1): Promise<Uint8Array> {
|
||||
try {
|
||||
const template = new ExcelTemplate();
|
||||
let templateBuff = await fs.promises.readFile(`${base}/${TEMPLATE_FOLDER_NAME}/${tdata.template}.xlsx`)
|
||||
await template.load(templateBuff);
|
||||
await template.process(tab,tdata.data)
|
||||
const buffer = await template.build({ type: 'uint8array' })
|
||||
if (outputMediaType === "xlsx")
|
||||
return buffer as Uint8Array
|
||||
const libreOfficeFileConverter = new LibreOfficeFileConverter({
|
||||
childProcessOptions: {
|
||||
timeout: 60 * 1000,
|
||||
},
|
||||
});
|
||||
const lbuffer = await libreOfficeFileConverter.convertBuffer(Buffer.from(buffer as Uint8Array), outputMediaType);
|
||||
return lbuffer
|
||||
|
||||
} catch (e) {
|
||||
throw (e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** javascript-obfuscator:disable
|
||||
export async function xlsxTemplateX(templateBuff: Buffer, tdata: templateData, outputMediaType: string = "xlsx", tab: number = 1): Promise<Uint8Array> {
|
||||
try {
|
||||
const template = new ExcelTemplate()
|
||||
// let templateBuff = await fs.promises.readFile(`${base}/${TEMPLATE_FOLDER_NAME}/${tdata.template}.xlsx`)
|
||||
await template.load(templateBuff)
|
||||
await template.process(tab, tdata.data)
|
||||
const buffer = await template.build({ type: "uint8array" })
|
||||
if (outputMediaType === "xlsx") return buffer as Uint8Array
|
||||
const libreOfficeFileConverter = new LibreOfficeFileConverter({
|
||||
childProcessOptions: {
|
||||
timeout: 60 * 1000,
|
||||
},
|
||||
})
|
||||
const lbuffer = await libreOfficeFileConverter.convertBuffer(Buffer.from(buffer as Uint8Array), outputMediaType)
|
||||
return lbuffer
|
||||
} catch (e) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/** javascript-obfuscator:disable
|
||||
* @swagger
|
||||
* /api/v1/report-template/xlsx:
|
||||
* get:
|
||||
|
|
@ -53,23 +50,23 @@ export async function xlsxTemplateX(base: string=".", tdata: templateData, outpu
|
|||
* applicatin/json:
|
||||
* schema:
|
||||
* type: array
|
||||
* items:
|
||||
* items:
|
||||
* type: string
|
||||
* example: ["hello"]
|
||||
* 500:
|
||||
* description: Server error
|
||||
*/
|
||||
*/
|
||||
xlsxTemplateRoute.get("/", async function (req, res) {
|
||||
try {
|
||||
const fileList = await fs.promises.readdir(`./${TEMPLATE_FOLDER_NAME}`)
|
||||
const templateList = fileList.map((f) => f.split('.xlsx')[0])
|
||||
res.send(templateList)
|
||||
} catch (ex) {
|
||||
res.statusCode = 500;
|
||||
res.statusMessage = 'Internal Server Error during get xlsx template list';
|
||||
res.end(res.statusMessage);
|
||||
console.error('Error during get template list: ', ex);
|
||||
}
|
||||
try {
|
||||
const fileList = await fs.promises.readdir(`./${TEMPLATE_FOLDER_NAME}`)
|
||||
const templateList = fileList.map(f => f.split(".xlsx")[0])
|
||||
res.send(templateList)
|
||||
} catch (ex) {
|
||||
res.statusCode = 500
|
||||
res.statusMessage = "Internal Server Error during get xlsx template list"
|
||||
res.end(res.statusMessage)
|
||||
console.error("Error during get template list: ", ex)
|
||||
}
|
||||
})
|
||||
|
||||
/** javascript-obfuscator:disable
|
||||
|
|
@ -78,12 +75,20 @@ xlsxTemplateRoute.get("/", async function (req, res) {
|
|||
* post:
|
||||
* summary: สร้างเอกสารจาก xlsx template แล้วส่งกลับมาเป็น xlsx pdf odt , ค่า template เป็นชื่อของ template ที่ใช้งาน, reportName เป็นชื่อไฟล์ที่ต้องการ
|
||||
* tags: [report-template]
|
||||
* parameters:
|
||||
* - name: folder
|
||||
* in: query
|
||||
* description: ชื่อโฟลเดอร์
|
||||
* required: false
|
||||
* schema:
|
||||
* type: string
|
||||
* example: test
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/templateData'
|
||||
* $ref: '#/components/schemas/templateData'
|
||||
* example:
|
||||
* template: hello
|
||||
* reportName: xlsx-report
|
||||
|
|
@ -117,26 +122,167 @@ xlsxTemplateRoute.get("/", async function (req, res) {
|
|||
*
|
||||
*/
|
||||
xlsxTemplateRoute.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 xlsxTemplateX(".",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';
|
||||
res.end(res.statusMessage);
|
||||
console.error('Error during apply template: ', ex);
|
||||
}
|
||||
|
||||
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 template = null
|
||||
// Save the converted file to disk
|
||||
if (req.query["folder"]) {
|
||||
template = await fs.promises.readFile(`./${TEMPLATE_FOLDER_NAME}/${req.query["folder"]}/${req.body.template}.xlsx`)
|
||||
} else {
|
||||
template = await fs.promises.readFile(`./${TEMPLATE_FOLDER_NAME}/${req.body.template}.xlsx`)
|
||||
}
|
||||
let buffer = await xlsxTemplateX(template, 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"
|
||||
res.end(res.statusMessage)
|
||||
console.error("Error during apply template: ", ex)
|
||||
}
|
||||
})
|
||||
|
||||
/** javascript-obfuscator:disable
|
||||
* @swagger
|
||||
* /api/v1/report-template/xlsx/upload:
|
||||
* post:
|
||||
* summary: อัพไฟล์ xlsx
|
||||
* tags: [report-template]
|
||||
* parameters:
|
||||
* - name: report_name
|
||||
* in: query
|
||||
* description: ชื่อไฟล์
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* example: report
|
||||
* - name: folder
|
||||
* in: query
|
||||
* description: ชื่อโฟลเดอร์
|
||||
* required: false
|
||||
* schema:
|
||||
* type: string
|
||||
* example: test
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/octet-stream:
|
||||
* schema:
|
||||
* type: string
|
||||
* format: binary
|
||||
* responses:
|
||||
* 201:
|
||||
* description: file was converted.
|
||||
* content:
|
||||
* application/octet-stream:
|
||||
* schema:
|
||||
* type: string
|
||||
* format: binary
|
||||
* 400:
|
||||
* description: Invalid format
|
||||
* 500:
|
||||
* description: Server error
|
||||
*
|
||||
*/
|
||||
xlsxTemplateRoute.post("/upload", async function (req, res) {
|
||||
try {
|
||||
if (!req.headers["content-type"] || !req.headers["accept"] || !req.query["report_name"] || req.headers["content-type"] !== "application/octet-stream") {
|
||||
res.statusCode = 400
|
||||
res.statusMessage = "Require header: content-type(application/octet-stream) accept"
|
||||
res.end(res.statusMessage)
|
||||
console.log(req.headers["content-type"], req.headers["accept"], req.query["report_name"])
|
||||
return
|
||||
}
|
||||
// Determine the output media type and report name from headers
|
||||
let outputMediaType = mimeToExtension(req.headers["accept"])
|
||||
let reportName = req.query["report_name"]
|
||||
console.log("convert output: " + outputMediaType)
|
||||
|
||||
// Save the converted file to disk
|
||||
if (req.query["folder"]) {
|
||||
// Ensure the template folder exists
|
||||
await fs.promises.mkdir(`TEMPLATE_FOLDER_NAME/${req.query["folder"]}`, { recursive: true })
|
||||
await fs.promises.writeFile(`./${TEMPLATE_FOLDER_NAME}/${req.query["folder"]}/${reportName}.xlsx`, req.body)
|
||||
} else {
|
||||
// Ensure the template folder exists
|
||||
await fs.promises.mkdir(TEMPLATE_FOLDER_NAME, { recursive: true })
|
||||
await fs.promises.writeFile(`./${TEMPLATE_FOLDER_NAME}/${reportName}.xlsx`, req.body)
|
||||
}
|
||||
|
||||
// Send a response to the client
|
||||
res.statusCode = 201
|
||||
res.json({ message: "File converted and saved successfully" })
|
||||
} catch (ex) {
|
||||
res.statusCode = 500
|
||||
res.statusMessage = "Internal Server Error"
|
||||
res.end(res.statusMessage)
|
||||
console.error(`Error during convert with soffice:`, ex)
|
||||
}
|
||||
})
|
||||
|
||||
/** javascript-obfuscator:disable
|
||||
* @swagger
|
||||
* /api/v1/report-template/xlsx/download:
|
||||
* post:
|
||||
* summary: โหลดไฟล์ xlsx
|
||||
* tags: [report-template]
|
||||
* parameters:
|
||||
* - name: folder
|
||||
* in: query
|
||||
* description: ชื่อโฟลเดอร์
|
||||
* required: false
|
||||
* schema:
|
||||
* type: string
|
||||
* example: test
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/templateData'
|
||||
* example:
|
||||
* template: xlsx-report
|
||||
* responses:
|
||||
* 201:
|
||||
* description: เอกสารถูกสร้างขึ้น
|
||||
* content:
|
||||
* application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
|
||||
* schema:
|
||||
* type: string
|
||||
* format: binary
|
||||
* 500:
|
||||
* description: Server error
|
||||
*
|
||||
*/
|
||||
xlsxTemplateRoute.post("/download", async function (req, res) {
|
||||
try {
|
||||
if (!req.headers["content-type"] || !req.headers["accept"] || !req.body.template) 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 = null
|
||||
if (req.query["folder"]) {
|
||||
buffer = await fs.promises.readFile(`./${TEMPLATE_FOLDER_NAME}/${req.query["folder"]}/${req.body.template}.xlsx`)
|
||||
} else {
|
||||
buffer = await fs.promises.readFile(`./${TEMPLATE_FOLDER_NAME}/${req.body.template}.xlsx`)
|
||||
}
|
||||
res.statusCode = 201
|
||||
res.setHeader("Content-Type", req.headers["accept"])
|
||||
res.setHeader("Content-Disposition", `attachment;filename=${req.body.template}.${outputMediaType}`)
|
||||
res.setHeader("Content-Length", buffer.length)
|
||||
res.end(buffer)
|
||||
} catch (ex) {
|
||||
res.statusCode = 500
|
||||
res.statusMessage = "Internal Server Error during get xlsx template list"
|
||||
res.end(res.statusMessage)
|
||||
console.error("Error during apply template: ", ex)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
5229
package-lock.json
generated
5229
package-lock.json
generated
File diff suppressed because it is too large
Load diff
76
package.json
76
package.json
|
|
@ -1,39 +1,41 @@
|
|||
{
|
||||
"name": "report-server-ts",
|
||||
"version": "1.0.0",
|
||||
"description": "docx-template มีปัญหากับ bun คาดว่าเป็นปัญหาจาก eval",
|
||||
"scripts": {
|
||||
"dev": "PORT=3001 nodemon app.ts",
|
||||
"swaggergen": "ts-node libs/create-swagger-spec.ts ",
|
||||
"build": "ts-node libs/create-swagger-spec.ts && tsc && cp libs/swagger-specs.json dist/libs",
|
||||
"serve": "PORT=3000 node dist/app.js",
|
||||
"obfuscator": "tsc && javascript-obfuscator ./dist --output ./dist2 && cp libs/swagger-specs.json dist/libs",
|
||||
"preview": "PORT=3000 node dist2/app.js",
|
||||
"build:docker": "ts-node libs/create-swagger-spec.ts && tsc && javascript-obfuscator ./dist --output ./dist2&& cp libs/swagger-specs.json dist2/libs && docker build -t docker.frappet.com/demo/report-server .",
|
||||
"push:docker": "docker push docker.frappet.com/demo/report-server"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cors": "^2.8.5",
|
||||
"docx-templates": "^4.13.0",
|
||||
"express": "^4.19.2",
|
||||
"libreoffice-file-converter": "^2.3.3",
|
||||
"swagger-jsdoc": "^6.2.8",
|
||||
"swagger-ui-express": "^5.0.1",
|
||||
"xlsx-template-next": "^1.0.3",
|
||||
"yaqrcode": "^0.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/node": "^20.14.9",
|
||||
"@types/swagger-jsdoc": "^6.0.4",
|
||||
"@types/swagger-ui-express": "^4.1.6",
|
||||
"javascript-obfuscator": "^4.1.1",
|
||||
"nodemon": "^3.1.4",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.2.2"
|
||||
"name": "report-server-ts",
|
||||
"version": "1.0.0",
|
||||
"description": "docx-template มีปัญหากับ bun คาดว่าเป็นปัญหาจาก eval",
|
||||
"scripts": {
|
||||
"dev": "PORT=3001 nodemon app.ts",
|
||||
"swaggergen": "ts-node libs/create-swagger-spec.ts ",
|
||||
"build": "ts-node libs/create-swagger-spec.ts && tsc && cp libs/swagger-specs.json dist/libs",
|
||||
"serve": "PORT=3000 node dist/app.js",
|
||||
"obfuscator": "tsc && javascript-obfuscator ./dist --output ./dist2 && cp libs/swagger-specs.json dist/libs",
|
||||
"preview": "PORT=3000 node dist2/app.js",
|
||||
"build:docker": "ts-node libs/create-swagger-spec.ts && tsc && javascript-obfuscator ./dist --output ./dist2&& cp libs/swagger-specs.json dist2/libs && docker build -t docker.frappet.com/demo/report-server .",
|
||||
"push:docker": "docker push docker.frappet.com/demo/report-server"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^1.7.7",
|
||||
"cors": "^2.8.5",
|
||||
"docx-templates": "^4.13.0",
|
||||
"express": "^4.19.2",
|
||||
"libreoffice-file-converter": "^2.3.3",
|
||||
"swagger-jsdoc": "^6.2.8",
|
||||
"swagger-ui-express": "^5.0.1",
|
||||
"xlsx-template-next": "^1.0.3",
|
||||
"yaqrcode": "^0.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/node": "^20.14.9",
|
||||
"@types/swagger-jsdoc": "^6.0.4",
|
||||
"@types/swagger-ui-express": "^4.1.6",
|
||||
"javascript-obfuscator": "^4.1.1",
|
||||
"nodemon": "^3.1.4",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.2.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue