eCourt-note/app/api/template/generate/route.ts

116 lines
No EOL
4.1 KiB
TypeScript

// สร้าง docx จาก json
// - json.info.ticket_data จะมี tid ให้โหลดไฟล์ template นี้มาใช้
// - สร้าง signature/hash จาก json.info.ticket_data
import { NextRequest, NextResponse } from 'next/server';
import {readFile} from 'fs/promises';
import path from 'path';
import {DocumentTemplate,applyTemplate} from "@/lib/lib-tmpl";
import { docxPool } from '@/lib/docx-pool';
export const runtime = 'nodejs';
const EXTERNAL_API_KEY = process.env.EXTERNAL_API_KEY || '';
const PRIVATE_KEY_HEX = process.env.PRIVATE_KEY_HEX ||''
const SECRET = process.env.SECRET || 'super_secret'
const TMPL_PATH = process.env.TMPL_PATH || "./public/tmpl";
const TICKET_SEC = Number(process.env.TICKET_SEC||'120')
export async function POST(request: NextRequest) {
if (!EXTERNAL_API_KEY || !PRIVATE_KEY_HEX || !SECRET){
return NextResponse.json(
{ error: 'Server Error: require EXTERNAL_API_KEY PRIVATE_KEY_HEX and SECRET' },
{ status: 500 }
);
}
// 1. ตรวจสอบ API Key จาก HTTP Header (x-api-key)
const apiKey = request.headers.get('x-api-key')||'';
if (!apiKey || apiKey !== EXTERNAL_API_KEY) {
return NextResponse.json(
{ error: 'Unauthorized: Invalid API Key ' },
{ status: 401 }
);
}
try {
// รับข้อมูล JSON Payload
const templateData:DocumentTemplate = (await request.json());
// console.log(templateData)
// ต้องมี templateData.info.ticket_data เป็น json string เสมอ
if (!templateData || !templateData.info ||
!templateData.info.ticket_data ||
typeof templateData.info.ticket_data !== "string"
) {
return NextResponse.json(
{
error: "template/generate json.info.ticket_data not avaliable",
},
{ status: 400 },
);
}
const ticketObj = JSON.parse(templateData.info.ticket_data)
const tid = String(ticketObj.tid)
const fid = String(ticketObj.fid)
const uid = String(ticketObj.uid)
if(!tid||!fid||!uid)
{
return NextResponse.json(
{
error: "template/generate require json.info.ticket_data.(fid|tid|uid)",
},
{ status: 400 },
);
}
//เปิดไฟล์ template
const tmplPath = path.join(TMPL_PATH, `${path.basename(tid)}.docx`);
let templateBuffer: Buffer = await readFile(tmplPath)
// const output = await applyTemplate(templateBuffer, templateData, SECRET, PRIVATE_KEY_HEX, TICKET_SEC);
const output = await docxPool.run({
templateBuffer,
templateData,
secret: SECRET,
privateKeyHex: PRIVATE_KEY_HEX,
ticketSec: TICKET_SEC
});
const outputBuffer = Buffer.from(output);
// สร้าง ReadableStream ของไฟล์ .docx
// ในโค้ดจริง ส่วนนี้จะดึง Binary Buffer จาก Library เช่น docx, docxtemplater หรืออ่านจาก File System
// const encoder = new TextEncoder();
const docxStream = new ReadableStream({
start(controller) {
controller.enqueue(outputBuffer);
controller.close();
},
});
// 4. ส่ง Return เป็น Response พร้อม Stream และ Headers กำหนด MIME type ของ MS Word
const dlFileName = encodeURIComponent(`${tid}_${fid}_${uid}XX`)
return new NextResponse(docxStream, {
status: 200,
headers: {
'Content-Type':
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'Content-Disposition': `attachment; filename="${dlFileName}.docx"`,
'Cache-Control': 'no-store, max-age=0',
},
});
} catch (error:any) {
if ( error.code === 'ENOENT') {
return NextResponse.json(
{ error: 'NotFound: Invalid template ID or incorrect storage path'},
{ status: 404 }
);
}
console.error('Error generating docx:', error);
return NextResponse.json(
{ error: 'Failed to generate document payload'},
{ status: 500 }
);
}
}