first commit
This commit is contained in:
144
server.js
Normal file
144
server.js
Normal file
@@ -0,0 +1,144 @@
|
||||
const fastify = require('fastify')({
|
||||
logger: true,
|
||||
bodyLimit: 100 * 1024 * 1024 // 設置為 100MB
|
||||
});
|
||||
const { PDFDocument, PDFName, StandardFonts, PDFString, PDFPermissionFlag } = require('pdf-lib');
|
||||
const cors = require('@fastify/cors');
|
||||
|
||||
// 更詳細的 CORS 設置
|
||||
fastify.register(cors, {
|
||||
origin: ['*', 'null'],
|
||||
methods: ['GET', 'POST', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type']
|
||||
});
|
||||
|
||||
// 處理 PDF 生成請求
|
||||
fastify.post('/generate-pdf', {
|
||||
bodyLimit: 100 * 1024 * 1024, // 100MB
|
||||
}, async (request, reply) => {
|
||||
try {
|
||||
const { frames, settings } = request.body;
|
||||
|
||||
// 檢查 frames 是否為有效數組
|
||||
if (!Array.isArray(frames) || frames.length === 0) {
|
||||
throw new Error('No frames provided or frames is not an array');
|
||||
}
|
||||
|
||||
// 創建 PDF 文件
|
||||
const pdfDoc = await PDFDocument.create();
|
||||
|
||||
// 設置 PDF 元數據
|
||||
if (settings.title) pdfDoc.setTitle(settings.title);
|
||||
if (settings.author) pdfDoc.setAuthor(settings.author);
|
||||
if (settings.subject) pdfDoc.setSubject(settings.subject);
|
||||
if (settings.keywords) pdfDoc.setKeywords(Array.isArray(settings.keywords) ? settings.keywords : []);
|
||||
if (settings.creator) pdfDoc.setCreator(settings.creator);
|
||||
if (settings.producer) pdfDoc.setProducer(settings.producer);
|
||||
if (settings.language) pdfDoc.setLanguage(settings.language);
|
||||
|
||||
// 設置日期
|
||||
pdfDoc.setCreationDate(settings.creationDate ? new Date(settings.creationDate) : new Date());
|
||||
pdfDoc.setModificationDate(settings.modificationDate ? new Date(settings.modificationDate) : new Date());
|
||||
|
||||
// 根據品質設定調整圖片品質
|
||||
const qualitySettings = {
|
||||
low: { scale: 1 },
|
||||
medium: { scale: 2 },
|
||||
high: { scale: 3 }
|
||||
};
|
||||
const quality = qualitySettings[settings.quality || 'medium'];
|
||||
|
||||
// 處理每個 Frame
|
||||
for (const frame of frames) {
|
||||
if (!frame.imageBase64) {
|
||||
fastify.log.warn(`No image data for frame: ${frame.name}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// 解碼 base64 圖片數據
|
||||
const imageBuffer = Buffer.from(frame.imageBase64, 'base64');
|
||||
|
||||
// 嵌入圖片到 PDF
|
||||
const image = await pdfDoc.embedPng(imageBuffer);
|
||||
|
||||
// 獲取圖片尺寸
|
||||
const { width, height } = image.scale(1);
|
||||
|
||||
// 添加新頁面
|
||||
const page = pdfDoc.addPage([width, height]);
|
||||
|
||||
// 繪製圖片
|
||||
page.drawImage(image, {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width,
|
||||
height,
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
fastify.log.error(`Error processing frame ${frame.name}: ${error.message}`);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 檢查是否有頁面被添加
|
||||
if (pdfDoc.getPageCount() === 0) {
|
||||
throw new Error('No valid frames were processed');
|
||||
}
|
||||
|
||||
// 處理加密設置
|
||||
if (settings.encryption?.enabled) {
|
||||
// 定義權限映射
|
||||
const permissionsMap = {
|
||||
printing: PDFPermissionFlag.Print,
|
||||
modifying: PDFPermissionFlag.ModifyDocument,
|
||||
copying: PDFPermissionFlag.Extract,
|
||||
annotating: PDFPermissionFlag.Modify,
|
||||
};
|
||||
|
||||
// 收集啟用的權限
|
||||
const permissions = [];
|
||||
if (settings.encryption.permissions?.printing) permissions.push(permissionsMap.printing);
|
||||
if (settings.encryption.permissions?.modifying) permissions.push(permissionsMap.modifying);
|
||||
if (settings.encryption.permissions?.copying) permissions.push(permissionsMap.copying);
|
||||
if (settings.encryption.permissions?.annotating) permissions.push(permissionsMap.annotating);
|
||||
|
||||
// 應用加密設置
|
||||
await pdfDoc.encrypt({
|
||||
userPassword: settings.encryption.userPassword || undefined,
|
||||
ownerPassword: settings.encryption.ownerPassword || undefined,
|
||||
permissions: permissions
|
||||
});
|
||||
}
|
||||
|
||||
// 生成 PDF
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
|
||||
// 設置響應頭
|
||||
reply.header('Content-Type', 'application/pdf');
|
||||
reply.header('Content-Disposition', `attachment; filename=${settings.filename || 'figma-export.pdf'}`);
|
||||
|
||||
return reply.send(Buffer.from(pdfBytes));
|
||||
|
||||
} catch (error) {
|
||||
fastify.log.error(error);
|
||||
reply.code(500).send({
|
||||
error: 'Failed to generate PDF',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 啟動服務器
|
||||
const start = async () => {
|
||||
try {
|
||||
await fastify.listen({ port: 3000, host: '0.0.0.0' });
|
||||
console.log('Server running at http://localhost:3000');
|
||||
} catch (err) {
|
||||
fastify.log.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
start();
|
||||
Reference in New Issue
Block a user