Add generate API, Prototype for developer, Clean data
Some checks failed
Deploy eCourt Note Web to Server / Validate Database Schema (Drizzle) (push) Successful in 5s
Deploy eCourt Note Web to Server / Build Web Docker Image (push) Failing after 1m11s
Deploy eCourt Note Web to Server / Deploy eCourt Note Web to Server (push) Has been skipped
Deploy eCourt Note Web to Server / Notify Deployment Status (push) Failing after 0s
Some checks failed
Deploy eCourt Note Web to Server / Validate Database Schema (Drizzle) (push) Successful in 5s
Deploy eCourt Note Web to Server / Build Web Docker Image (push) Failing after 1m11s
Deploy eCourt Note Web to Server / Deploy eCourt Note Web to Server (push) Has been skipped
Deploy eCourt Note Web to Server / Notify Deployment Status (push) Failing after 0s
This commit is contained in:
parent
6ce071ee14
commit
a3d14fd58d
26 changed files with 911 additions and 1267 deletions
108
app/api/template/download-docx/route.ts
Normal file
108
app/api/template/download-docx/route.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// ตัวอย่างรองรับค่าจาก Frontend ที่เป็น Vanilla JavaScript และ Classic Framework
|
||||
// โดย ผ่าน Form หรือ การกดลิงค์(GET) เปลี่ยนหน้าเพื่อดาว์นโหลดไฟล์
|
||||
// จะมีข้อมูล info.ticket_data ที่สมบูรณ์แล้ว({fid,tid,uid,uname})แล้วเเรียก /api/template/generate เพื่อสร้างเอกสาร docx
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import path from 'path';
|
||||
import fs from 'fs/promises';
|
||||
|
||||
const DOCEDIT_BASE_URL = process.env.DOCEDIT_BASE_URL??"";
|
||||
const EXTERNAL_API_KEY = process.env.EXTERNAL_API_KEY??"";
|
||||
const TMPL_PATH = process.env.TMPL_PATH??"";
|
||||
if (!DOCEDIT_BASE_URL||!EXTERNAL_API_KEY||!TMPL_PATH) {
|
||||
console.error('Missing variable DOCEDIT_BASE_URL, EXTERNAL_API_KEY or TMPL_PATH')
|
||||
}
|
||||
|
||||
|
||||
async function processRequest(fid: string,tid:string,uid:string,uname:string):Promise<NextResponse<unknown>>
|
||||
{
|
||||
// console.log("processRequest get:",fid,tid,uid,uname)
|
||||
// console.log(process.cwd())
|
||||
const filePath = path.join(TMPL_PATH,`${fid}.json`);
|
||||
try {
|
||||
if (!fid||!tid||!uid||!uname) {
|
||||
return NextResponse.json({ error: 'Missing fid, tid, uid or uname' }, { status: 400 });
|
||||
}
|
||||
|
||||
// อ่านไฟล์ JSON จำลองการอ่านจากฐานข้อมูล
|
||||
const rawJson = await fs.readFile(filePath, 'utf-8');
|
||||
const jsonData = JSON.parse(rawJson);
|
||||
if (!jsonData || typeof jsonData !== 'object' ) {
|
||||
return NextResponse.json({error:'Invalid data format'}, { status: 400 });
|
||||
}
|
||||
|
||||
//!! ตรวจสอบสิทธิ์ผู้ใช้ uid ว่ามีสิทธิ์เข้าถึงไฟล์ fid หรือไม่เพื่อกันการการยิง API ตรงๆ ไม่ผ่าน Frontend!!
|
||||
|
||||
// ข้อมูลจำเป็นต้องมี prop นี้เสมอถ้าไม่มีให้สร้าง jsonData.info.ticket_data
|
||||
if(!Object.hasOwn(jsonData, 'info'))
|
||||
jsonData['info']={}
|
||||
jsonData.info['ticket_data'] = JSON.stringify({fid,tid,uid,uname})
|
||||
// sign เองตรงนี้ให้อยู่ในรูปแบบ data.info={ticket_data,HmacSha256,Ed25519} หรือว่างไว้ให้ docedit สร้างให้
|
||||
|
||||
//ยิงไปหาระบบ Docedit เพื่อเอา Stream
|
||||
// console.log(`fetch ${DOCEDIT_BASE_URL}/api/template/generate`)
|
||||
const docxResponse = await fetch(`${DOCEDIT_BASE_URL}/api/template/generate`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': EXTERNAL_API_KEY,
|
||||
},
|
||||
body: JSON.stringify(jsonData),
|
||||
});
|
||||
|
||||
// เช็ค Content-Type และ Status ก่อน
|
||||
const contentType = docxResponse.headers.get('content-type') || '';
|
||||
|
||||
if (!docxResponse.ok || contentType.includes('text/html')) {
|
||||
const errorText = await docxResponse.text();
|
||||
console.error('download-docx:Invalid docx Response:', errorText);
|
||||
|
||||
return NextResponse.json(
|
||||
{error:`Error from docedit generate: Expected docx stream but received ${contentType} (Status ${docxResponse.status})`},
|
||||
{ status: 502 }
|
||||
);
|
||||
}
|
||||
|
||||
// 2. ดึง ReadableStream โดยตรงจาก Response ของระบบ
|
||||
const stream = docxResponse.body;
|
||||
|
||||
// 3. ส่ง Binary Stream กลับไปยัง Browser พร้อม Header กำหนดประเภทไฟล์
|
||||
const download_file = `${fid}_${uid}_xxx`
|
||||
return new NextResponse(stream as unknown as BodyInit, {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type':
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'Content-Disposition': `attachment; filename="${encodeURIComponent(download_file)}.docx"`,
|
||||
'Cache-Control': 'no-store, max-age=0',
|
||||
},
|
||||
});
|
||||
} catch (error:any) {
|
||||
if ( error.code === 'ENOENT') {
|
||||
return NextResponse.json(
|
||||
{ error: `Data not found: ${filePath}`},
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
console.error(error)
|
||||
return NextResponse.json({error:'Internal Server Error'}, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest)
|
||||
{
|
||||
const searchParams = request.nextUrl.searchParams;
|
||||
const fid = searchParams.get('fid') || '';
|
||||
const tid = searchParams.get('tid') || '';
|
||||
const uid = searchParams.get('uid') || '';
|
||||
const uname = searchParams.get('uname') || '';
|
||||
return await processRequest(fid,tid,uid,uname)
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const formData = await request.formData();
|
||||
const fid = String(formData.get('fid'))
|
||||
const tid = String(formData.get('tid'))
|
||||
const uid = String(formData.get('uid'))
|
||||
const uname = String(formData.get('uname'))
|
||||
return await processRequest(fid,tid,uid,uname)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue