| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- // ZIP 打包处理模块
- // 负责接收图片和 JSON 数据,打包成 ZIP 文件并返回
- const archiver = require('archiver');
- const http = require('http');
- class ZipHandler {
- /**
- * 处理打包请求
- * @param {http.IncomingMessage} req - HTTP 请求对象
- * @param {http.ServerResponse} res - HTTP 响应对象
- */
- static handlePackRequest(req, res) {
- if (req.method !== 'POST') {
- res.writeHead(405, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify({ error: 'Method not allowed' }));
- return;
- }
- let body = '';
-
- req.on('data', (chunk) => {
- body += chunk.toString();
- });
- req.on('end', () => {
- try {
- const data = JSON.parse(body);
- const { folderName, imageData, jsonData } = data;
- if (!folderName || !imageData || !jsonData) {
- res.writeHead(400, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify({ error: 'Missing required fields: folderName, imageData, jsonData' }));
- return;
- }
- // 创建 ZIP 文件
- this.createZip(folderName, imageData, jsonData, res);
- } catch (error) {
- console.error('[ZipHandler] 解析请求数据失败:', error);
- res.writeHead(400, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify({ error: 'Invalid JSON data', details: error.message }));
- }
- });
- req.on('error', (error) => {
- console.error('[ZipHandler] 请求错误:', error);
- res.writeHead(500, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify({ error: 'Request error', details: error.message }));
- });
- }
- /**
- * 创建 ZIP 文件并返回
- * @param {string} folderName - 文件夹名称
- * @param {string} imageData - Base64 编码的图片数据
- * @param {string} jsonData - JSON 字符串数据
- * @param {http.ServerResponse} res - HTTP 响应对象
- */
- static createZip(folderName, imageData, jsonData, res) {
- try {
- // 验证输入数据
- if (!imageData || typeof imageData !== 'string') {
- throw new Error('imageData 必须是字符串');
- }
-
- if (!jsonData || typeof jsonData !== 'string') {
- throw new Error('jsonData 必须是字符串');
- }
- // 清理 Base64 数据:移除可能存在的 data URL 前缀
- let cleanImageData = imageData;
- if (cleanImageData.includes(',')) {
- // 如果包含逗号,说明可能有 data:image/...;base64, 前缀
- const base64Index = cleanImageData.indexOf(',');
- cleanImageData = cleanImageData.substring(base64Index + 1);
- }
-
- // 移除可能的空白字符
- cleanImageData = cleanImageData.trim();
- // 验证 Base64 格式
- if (!/^[A-Za-z0-9+/=]+$/.test(cleanImageData)) {
- throw new Error('imageData 不是有效的 Base64 格式');
- }
- // 设置响应头
- res.writeHead(200, {
- 'Content-Type': 'application/zip',
- 'Content-Disposition': `attachment; filename="${encodeURIComponent(folderName)}.zip"`,
- 'Access-Control-Allow-Origin': '*'
- });
- // 创建 archiver 实例
- const archive = archiver('zip', {
- zlib: { level: 6 } // 压缩级别
- });
- // 监听错误
- archive.on('error', (err) => {
- console.error('[ZipHandler] ZIP 创建错误:', err);
- if (!res.headersSent) {
- res.writeHead(500, {
- 'Content-Type': 'application/json',
- 'Access-Control-Allow-Origin': '*'
- });
- res.end(JSON.stringify({ error: 'Failed to create zip', details: err.message }));
- } else {
- // 如果响应头已发送,尝试结束响应
- try {
- res.end();
- } catch (e) {
- console.error('[ZipHandler] 无法结束响应:', e);
- }
- }
- });
- // 监听响应错误
- res.on('error', (err) => {
- console.error('[ZipHandler] 响应错误:', err);
- archive.abort();
- });
- // 将 ZIP 流连接到响应
- archive.pipe(res);
- // 将 Base64 图片数据转换为 Buffer
- let imageBuffer;
- try {
- imageBuffer = Buffer.from(cleanImageData, 'base64');
- if (imageBuffer.length === 0) {
- throw new Error('Base64 解码后图片数据为空');
- }
- } catch (bufferError) {
- throw new Error(`Base64 解码失败: ${bufferError.message}`);
- }
-
- // 添加文件到 ZIP
- archive.append(imageBuffer, { name: `${folderName}.png` });
- archive.append(jsonData, { name: `${folderName}.json` });
- // 完成打包
- archive.finalize();
- console.log(`[ZipHandler] ✓ 成功创建 ZIP: ${folderName}.zip`);
- } catch (error) {
- console.error('[ZipHandler] 创建 ZIP 失败:', error);
- if (!res.headersSent) {
- res.writeHead(500, {
- 'Content-Type': 'application/json',
- 'Access-Control-Allow-Origin': '*'
- });
- res.end(JSON.stringify({ error: 'Failed to create zip', details: error.message }));
- } else {
- // 如果响应头已发送,尝试结束响应
- try {
- res.end();
- } catch (e) {
- console.error('[ZipHandler] 无法结束响应:', e);
- }
- }
- }
- }
- }
- module.exports = ZipHandler;
|