url 2 pdf support, update test run, reduse imge size,
This commit is contained in:
parent
e921875bde
commit
f6b68e4379
32 changed files with 3851 additions and 1108 deletions
231
README.md
231
README.md
|
|
@ -1,29 +1,24 @@
|
|||
# report-server-ts
|
||||
เป็น Web API ออกแบบมาเพื่อสร้างเอกสารจาก templste สามารถใช้ frontend โดยตรง เพื่อจะได้ไม่ต้องทำ backend เพื่อสร้างเอกสารเฉพาะตัวออกมา
|
||||
เป็น Microservice(Web API) ออกแบบมาเพื่อสร้างเอกสารจาก templste หรือแปลงไฟล์
|
||||
สามารถใช้ซ้ำได้หลายโปรเจ็ก
|
||||
|
||||
|
||||
## Feature & Change
|
||||
- แก้ไขจากเดิมตัวเดิมเป็น JavaScript เป็น TypeScript ตัด pandoc ออก
|
||||
- ใช้ docx xlsx เป็น template เพื่อสร้างเอกสารคล้าย Mail Merge ลูกค้าออกแบบเองได้
|
||||
- รายงานที่ได้เป็นไฟล์แบบเดียวกับ template หรือแปลงเป็น pdf หรือฟอร์แม็ตของ LibreOffice ได้
|
||||
- แปลงไฟล์จาก MS Office เป็น PDF รองรับการตัดคำไทย
|
||||
- ใช้ไฟล์ docx/xlsx เป็น template คล้าย Mail Merge ยูสเซอร์ออกแบบเองได้ รวมกับ ข้อมูลใน JSON เพื่อออกเป็น docx/xlsx
|
||||
- JSON + template จะได้ไฟล์ output ฟอร์แม็ตจะเป็นไฟล์ของ template(docx/xlsx) สามารถแปลเป็นฟอร์แม็ต png, pdf, jpeg ฯลฯ ได้ด้วยความสามารถของ Libreoffice(soffice)
|
||||
- ใช้ url ของหน้าเวปแปลงเป็นไฟล์รองรับ pdf, png, jpeg เพื่อออกรายงานจากหน้าเวปได้ รองรับ Query Selector
|
||||
- แปลงไฟล์เป็น ภาพหรือ PDF รองรับการตัดคำไทย (ตัวออกรายงานตัวอื่นๆมักจะมีปัญหาการตัดคำ)
|
||||
- โค้ดมีการ obfuscator เพื่อลดขนาดและกันลูกค้าเอาโค้ดไปใช้
|
||||
- มี Swagger ไว้ทดสอบ API มี libs/swagger-specs.json เพื่อนำเข้า Postman หรือเครื่องมื่อื่นๆได้
|
||||
- มีโปรแกรมช่วยทดสอบ template แบบง่ายๆ ให้ทดสอบก่อนเอาเข้าเซิร์ฟเวอร์
|
||||
- Docker Image จะใช้แบบ Standalone หรือเป็น Microservice ร่วมกับโปรเจ็กอื่นๆได้ ใช้งานทันที
|
||||
- Docker image เหลือ 1.76GB จากเดิม 3.5GB
|
||||
- build เป็น Docker Image เพื่อใช้ใน Microservice ในโปรเจ็กอื่นๆ ใช้ prefix /api/v1/report-template/* ลดขนาดแล้วด้วย node:22-bookworm-slim
|
||||
|
||||
## ติดตั้ง
|
||||
รันโปรเจ็กบน Linux ,clone project ติดตั้ง Fonts และ LibreOffice ตามวิธีใน Dockerfile แล้วไปหัวข้อการใช้งานได้เลย หัวนี้ไว้เพื่ออ้างอิงเท่านั้น ใช้ node 20.7.0 บน Linux AMD x86-64
|
||||
ตั้งค่าของ TypeScript [ตามเวปนี้](https://www.geeksforgeeks.org/how-to-use-express-in-typescript/) ให้ใช้ ES module ได้ด้วย
|
||||
## development
|
||||
พัฒนาและทดสอบบน node 22 ,Linux AMD x86-64 ให้ clone project ติดตั้ง Fonts และ LibreOffice ตามวิธีใน [Dockerfile](./Dockerfile)
|
||||
|
||||
```bash
|
||||
npm i express
|
||||
npm i -D typescript @types/express @types/node ts-node
|
||||
npm i docx-templates xlsx-template-next swagger-ui-express swagger-jsdoc yaqrcode cors libreoffice-file-converter
|
||||
npm i -D @types/swagger-ui-express @types/swagger-jsdoc @types/cors
|
||||
# obfuscate code tools
|
||||
npm i -D javascript-obfuscator
|
||||
# clone project
|
||||
npm install
|
||||
# add type support for yaqrcode
|
||||
cd node_modules/yaqrcode
|
||||
wget https://raw.githubusercontent.com/zenozeng/node-yaqrcode/master/index.d.ts
|
||||
|
|
@ -44,7 +39,7 @@ docker compose up -d
|
|||
npm run push:docker
|
||||
```
|
||||
|
||||
## ทดสอบ template
|
||||
## ทดสอบ template/unit test
|
||||
|
||||
ไปที่โฟลเดอร์ test-run มีโปรแกรมเพื่อทดสอบ template ให้ทดสอบที่นี้ก่อนเอา template ไปวางในเซิร์ฟเวอร์ มีค่า default สำหรับการทดสอบที่ใช้ได้เลย สามารถแปลงไปไฟล์แบบต่างๆที่ Libreoffice รองรับ(จำเป็นต้องติดตั้ง ) ควรทดสอบรูปแบบข้อมูล(json) ให้เข้ากับ template(docx,xlsx) ถ้าเกิดปัญหา ถ้าค่าไม่ครบ template แบบ docx จะ error log ที่เซิร์ฟเวอร์ ส่วน xlsx ไม่แจ้งปัญหา แค่ไม่แสดงค่านั้นๆ คู่มือการใช้งานที่สมบูรณ์ให้ไปที่เวปของ library ที่ใช้
|
||||
[docx-templates](https://www.npmjs.com/package/docx-templates) และ
|
||||
|
|
@ -61,20 +56,200 @@ $ npx ts-node xlsx-template.ts
|
|||
Output extension(xlsx,pdf): ods
|
||||
JSON data path(./xlsx.json):
|
||||
Base path of templates-docx(..):
|
||||
|
||||
$ npx ts-node html-template.ts
|
||||
```
|
||||
## API
|
||||
หลัง npm run dev ไปดูที่ [http://localhost:3001/swagger](http://localhost:3001/swagger)
|
||||
หรือใช้ Rest Client ดูไฟล์ [api.http](./api.http)
|
||||
|
||||
ตรง http header จะใช้ accept เป็นตัวบอกว่าต้องการผลเป็นไฟล์แบบไหนโดยใช้ [Mime type](https://developer.mozilla.org/en-US/docs/Web/HTTP/MIME_types/Common_types) เพื่อเป็นมาตรฐาน ให้ดูที่รองรับในฟังก์ชั่น [mimeToExtension](./libs/report-template.ts)
|
||||
|
||||
### HTML
|
||||
แปลงจาก URL เป็น pdf,png,jpg รองรับการตัดคำไทย ฟีเจอร์ template ยังไม่เสร็จ
|
||||
``` sh
|
||||
# Grafana dashboard to pdf
|
||||
curl -X 'POST' \
|
||||
'http://localhost:3001/api/v1/report-template/html' \
|
||||
-H 'accept: application/pdf' -H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"template": "https://bma-dashboard.frappet.synology.me/d/ANtkJay4z/4Lic4Li54LmJ4Lie4Li04LiB4Liy4Lij?orgId=1&kiosk",
|
||||
"reportName": "html-grafana",
|
||||
"htmlOption": {
|
||||
"querySelector": ".scrollbar-view"
|
||||
}
|
||||
}' -o html-grafana.pdf
|
||||
|
||||
# url to png
|
||||
curl -X 'POST' 'http://localhost:3001/api/v1/report-template/html' \
|
||||
-H 'accept: image/png' -H 'Content-Type: application/json' \
|
||||
-d '{"template": "https://www.blognone.com/","reportName": "html-blognone"}' -o html-blognone.png
|
||||
# url to jpeg
|
||||
curl -X 'POST' 'http://localhost:3001/api/v1/report-template/html' \
|
||||
-H 'accept: image/jpeg' -H 'Content-Type: application/json' \
|
||||
-d '{"template": "https://pantip.com/","reportName": "html-blognone"}' -o html-pantip.jpeg
|
||||
```
|
||||
|
||||
# Build docker
|
||||
```bash
|
||||
docker build -t docker.frappet.com/demo/report-server .
|
||||
docker push docker.frappet.com/demo/report-server
|
||||
docker run --name rserver -p 80:3000 docker.frappet.com/demo/report-server
|
||||
### docx
|
||||
แปลงจากเทมเพลทไฟล์ .docx เป็น docx,pdf,png
|
||||
```sh
|
||||
curl -X 'POST' \
|
||||
'https://report-server.frappet.synology.me/api/v1/report-template/docx?folder=command' \
|
||||
-H 'accept: application/vnd.openxmlformats-officedocument.wordprocessingml.document' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"template": "C-PM-01_cover",
|
||||
"reportName": "command-C-PM-01_cover",
|
||||
"data": {
|
||||
"issue": "............",
|
||||
"title": "......",
|
||||
"commandNo": "......",
|
||||
"commandYear": "......",
|
||||
"commandTitle": "คำสั่งบรรจุและแต่งตั้งผู้สอบแข่งขันได้",
|
||||
"detailHeader": "",
|
||||
"detailBody": "อาศัยอำนาจตามความในมาตรา ๔๔ มาตรา ๕๒ (๔) แห่งพระราชบัญญัติระเบียบข้าราชการกรุงเทพมหานครและบุคลากรกรุงเทพมหานคร พ.ศ.๒๕๕๔ ประกอบกับกฎ ก.ก. ว่าด้วยการทดลองปฏิบัติหน้าที่ราชการและการพัฒนาข้าราชการกรุงเทพมหานครสามัญที่อยู่ระหว่างทดลองปฏิบัติหน้าที่ราชการ พ.ศ. ๒๕๕๕ มติคณะกรรมการข้าราชการกรุงเทพมหานครและบุคลากรกรุงเทพมหานคร ครั้งที่ ๑/๒๕๕๔ เมื่อวันที่ ๒๒ ธันวาคม ๒๕๕๔ มติ อ.ก.ก. วิสามัญเกี่ยวกับระบบราชการ การจัดส่วนราชการและค่าตอบแทน ครั้งที่ ๙/๒๕๕๖ เมื่อ ๑๘ กันยายน ๒๕๕๖ ประกาศสำนักงาน ก.ก. ลงวันที่ ………………………………….. เรื่อง รับสมัครสอบแข่งขันเพื่อบรรจุและแต่งตั้งบุคคลเข้ารับราชการเป็นข้าราชการการกรุงเทพมหานครสามัญ ครั้งที่ ………………………………….. และประกาศสำนักงาน ก.ก. ลงวันที่ ………………………………….. เรื่อง ผลการสอบแข่งขันเพื่อบรรจุและแต่งตั้งบุคคลเข้ารับราชการเป็นข้าราชการกรุงเทพมหานครสามัญ ครั้งที่ ………………………………….. ตำแหน่ง………………………………….. ให้บรรจุผู้สอบแข่งขันได้เข้ารับราชการเป็นข้าราชการกรุงเทพมหานครสามัญ และแต่งตั้งให้ดำรงตำแหน่ง………………………………….. จำนวน ………………………………….. ราย โดยให้ทดลองปฏิบัติหน้าที่ราชการในตำแหน่งที่ได้รับแต่งตั้งดังบัญชีรายละเอียดแนบท้ายคำสั่งนี้",
|
||||
"detailFooter": "",
|
||||
"commandDate": "..................",
|
||||
"commandAffectDate": "..................",
|
||||
"commandExcecuteDate": "..................",
|
||||
"name": "....................................",
|
||||
"position": "ผู้อำนวยการสำนัก/เขต",
|
||||
"authorizedUserFullName": "............",
|
||||
"authorizedPosition": "..................."
|
||||
}
|
||||
}' -o docx-command-C-PM-01_cover.docx
|
||||
|
||||
|
||||
curl -X 'POST' \
|
||||
'https://report-server.frappet.synology.me/api/v1/report-template/docx?folder=command' \
|
||||
-H 'accept: application/pdf' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"template": "C-PM-01_cover",
|
||||
"reportName": "command-C-PM-01_cover",
|
||||
"data": {
|
||||
"issue": "............",
|
||||
"title": "......",
|
||||
"commandNo": "......",
|
||||
"commandYear": "......",
|
||||
"commandTitle": "คำสั่งบรรจุและแต่งตั้งผู้สอบแข่งขันได้",
|
||||
"detailHeader": "",
|
||||
"detailBody": "อาศัยอำนาจตามความในมาตรา ๔๔ มาตรา ๕๒ (๔) แห่งพระราชบัญญัติระเบียบข้าราชการกรุงเทพมหานครและบุคลากรกรุงเทพมหานคร พ.ศ.๒๕๕๔ ประกอบกับกฎ ก.ก. ว่าด้วยการทดลองปฏิบัติหน้าที่ราชการและการพัฒนาข้าราชการกรุงเทพมหานครสามัญที่อยู่ระหว่างทดลองปฏิบัติหน้าที่ราชการ พ.ศ. ๒๕๕๕ มติคณะกรรมการข้าราชการกรุงเทพมหานครและบุคลากรกรุงเทพมหานคร ครั้งที่ ๑/๒๕๕๔ เมื่อวันที่ ๒๒ ธันวาคม ๒๕๕๔ มติ อ.ก.ก. วิสามัญเกี่ยวกับระบบราชการ การจัดส่วนราชการและค่าตอบแทน ครั้งที่ ๙/๒๕๕๖ เมื่อ ๑๘ กันยายน ๒๕๕๖ ประกาศสำนักงาน ก.ก. ลงวันที่ ………………………………….. เรื่อง รับสมัครสอบแข่งขันเพื่อบรรจุและแต่งตั้งบุคคลเข้ารับราชการเป็นข้าราชการการกรุงเทพมหานครสามัญ ครั้งที่ ………………………………….. และประกาศสำนักงาน ก.ก. ลงวันที่ ………………………………….. เรื่อง ผลการสอบแข่งขันเพื่อบรรจุและแต่งตั้งบุคคลเข้ารับราชการเป็นข้าราชการกรุงเทพมหานครสามัญ ครั้งที่ ………………………………….. ตำแหน่ง………………………………….. ให้บรรจุผู้สอบแข่งขันได้เข้ารับราชการเป็นข้าราชการกรุงเทพมหานครสามัญ และแต่งตั้งให้ดำรงตำแหน่ง………………………………….. จำนวน ………………………………….. ราย โดยให้ทดลองปฏิบัติหน้าที่ราชการในตำแหน่งที่ได้รับแต่งตั้งดังบัญชีรายละเอียดแนบท้ายคำสั่งนี้",
|
||||
"detailFooter": "",
|
||||
"commandDate": "..................",
|
||||
"commandAffectDate": "..................",
|
||||
"commandExcecuteDate": "..................",
|
||||
"name": "....................................",
|
||||
"position": "ผู้อำนวยการสำนัก/เขต",
|
||||
"authorizedUserFullName": "............",
|
||||
"authorizedPosition": "..................."
|
||||
}
|
||||
}' -o docx-command-C-PM-01_cover.pdf
|
||||
|
||||
|
||||
curl -X 'POST' \
|
||||
-H 'accept: application/pdf' \
|
||||
-H 'Content-Type: application/json' \
|
||||
'http://localhost:3001/api/v1/report-template/docx' \
|
||||
-d '{
|
||||
"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": "พลสิทธิ์"
|
||||
}
|
||||
]
|
||||
}
|
||||
}' -o docx-report.pdf
|
||||
|
||||
```
|
||||
|
||||
# Bun Note
|
||||
เริ่มแรกในการพอร์ตจาก JavaScript ลองใช้ Bun(TypeScript) แทน Node.js ตัว Bun ค่อนข้างน่าประทับใจใช้ TypeScript โดยตรงไม่ต้องตั้งค่า หรือติดตั้งเพิ่ม แต่มีปัญหากับ libreoffice-file-converter ต้องแก้ค่าใน package.json
|
||||
docker-template ฟังก์ชั่นพื้นฐานใช้งานพอได้ ส่วน EXEC กับ custom function ทำงานไม่ได้ คาดว่าเป็นปัญหาจาก eval เลยกลับมาใช้ node เหมือนเดิม
|
||||
### xlsx
|
||||
แปลงจากเทมเพลทไฟล์ .xlsx เป็น xlsx,pdf,png
|
||||
|
||||
## Todo
|
||||
- รองรับ Authentication Header เพื่อให้ยูสเซอร์ในระบบใช้งานได้เท่านั้น
|
||||
```
|
||||
curl -X 'POST' \
|
||||
'http://localhost:3001/api/v1/report-template/xlsx' \
|
||||
-H 'accept: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
||||
}' -o xlsx-report.xlsx
|
||||
```
|
||||
|
||||
# Known Issue
|
||||
- soffice แปลงเป็น png หรือ jpeg ได้แค่ 96dpi มันฮาร์ดโค้ดอยู่ สามารถแก้โค้ด compile ใหม่(ยากไปหน่อย) work around(ยังไม่ได้ทำ) ภาพความละเอียดต่ำให้แปลงเป็น pdf แล้ว[แปลงเป็นภาพ](https://ask.libreoffice.org/t/change-default-resolution-in-batch-png-conversion/18464/2) ใช้ Imagemagick ในการแปลงข้อดีคือรองรับฟอร์แม็ตได้หลายแบบ แต่มัน [disable PDF เป็น default](https://stackoverflow.com/questions/52998331/imagemagick-security-policy-pdf-blocking-conversion) ต้องแก้คอนฟิกก่อน ค่อนช้างกิน CPU ถ้ามีการแปลงหลายต่อ วิธีการนี้อาจจะทำเป็น API ในอนาคต คำสั่งด้านล่างลองแล้วใช้ได้
|
||||
```
|
||||
convert -density 300 -background white -alpha remove report-docx.pdf report-docx2.png
|
||||
convert -density 300 -background white -alpha remove report-docx.pdf report-docx2.jpeg
|
||||
```
|
||||
- url แปลงเป็น pdf หรือภาพ จะเป็นหน้าเดียวเลย ยังไม่สามารถกำหนดขนาดทำเป็นหลายๆหน้าได้ อาจจะเป็นไปได้ยังหาวิธีอยู่เลยทำหน้าเดียวไปก่อน ยังมีปัญหากับการโหลดที่เป็น lazy load ยังไม่รองรับ Authentication header
|
||||
|
||||
## Note
|
||||
- ยังไม่สามารถใช้ bun runtime มีปัญหากับ libreoffice-file-converter และ docker-template เลยไม่ได้เอามาใช้ รุ่นใหม่อาจจะแก้ปัญหานี้แล้วต้องลองอีกที
|
||||
- Playwright ยังตรวจสอบความสูงของหน้าไม่ถูกต้องเลยใช้ puppeteer แทน
|
||||
- น่าจะทำให้รองรับ Authentication Header เพื่อให้ยูสเซอร์ในระบบใช้งานได้เท่านั้น
|
||||
- หาทางสร้างเอกสารจาก text เช่น Markdown เป็นเอกสาร MS Office
|
||||
- น่าจะทำ license key เผื่อขายให้ลูกค้าติดตั้งใช้งานต่อ (โค้ดที่ผ่าน obfuscator แล้วย้อนกลับมาได้ง่ายหรือเปล่า ?)
|
||||
- น่าจะทำ license key เผื่อขายให้ลูกค้าติดตั้งใช้งานต่อ (โค้ดที่ผ่าน obfuscator แล้วย้อนกลับมาได้ง่ายหรือเปล่า ?)
|
||||
- อาจจะลอง inkscape รองรับ command line อาจจะเอามาทำอะไรได้ "inkscape -z -e out.png -w 1024 in.svg"
|
||||
- การแปลงภาพสามารใช้ image magick ได้ยังไม่ได้ลอง
|
||||
- ถ้าใช้อิมเมจแบบ Distroless น่าจะเล็กลงแต่ตอนนี้ยังไม่มีรายการ library ที่จำเป็นทั้งหมดอีกทั้งอาจจะต้องใช้ shell เพื่อรัน soffice ใช้แบบ slim น่าจะเหมาะกับการนี้
|
||||
- docker image น่าจะทำให้ติดตั้ง font เพิ่มได้
|
||||
- ควรจำกัด domain ที่เรียกใช้ได้
|
||||
Loading…
Add table
Add a link
Reference in a new issue