AWS Lambda调用Prince生成PDF时出现write EPIPE错误求助
解决AWS Lambda调用Prince时的write EPIPE错误
问题背景
基于现有指南修改Lambda函数,改为通过URL获取HTML内容(使用axios),再传入Prince生成PDF。已确认传入Prince前的HTML内容与直接传HTML文件时完全一致,但仅URL版本触发write EPIPE错误,CloudWatch显示该错误,客户端返回null,尝试用Promise等待未解决。
解决方案
1. 统一用Promise管理异步流程
原代码中async handler与execFile回调混用,可能导致Lambda上下文提前结束引发EPIPE。将execFile包装为Promise,用async/await统一处理异步操作:
var execFile = require('child_process').execFile; const axios = require('axios'); function tinyMultipartParser(data) { const lines = data.split("\r\n"); const output = []; lines.forEach(line => { output.push(line.trim()); }) return output.join("\n"); } // 将execFile包装为Promise function runPrince(html) { return new Promise((resolve, reject) => { const child = execFile("./prince", ["-", "-o", "-"], (err, stdout, stderr) => { if (err) { const princeError = stderr.toString().match(/prince:\s+error:\s+([^\n]+)/); reject(new Error(princeError ? princeError[1] : err.message)); return; } resolve(stdout); }); // 监听子进程错误,捕获底层异常 child.on('error', (err) => { reject(new Error(`Process error: ${err.message}`)); }); // 写入HTML并处理写入错误 child.stdin.write(html, (writeErr) => { if (writeErr) { reject(new Error(`Write to stdin failed: ${writeErr.message}`)); } child.stdin.end(); }); }); } exports.handler = async (event) => { try { if (!event || !event.body) { return { statusCode: 400, body: JSON.stringify({ error: "No data provided" }) }; } let body = event.body; if (event.isBase64Encoded) { body = Buffer.from(body, "base64").toString("ascii"); } // 获取URL对应的HTML内容 const response = await axios.get(body); body = response.data; // 替换相对URL为绝对URL const baseUrl = 'https://embed.notMyRealDomain.com'; body = body.replace(/href="([^"]+)"/g, (match, relativeURL) => { const absoluteURL = new URL(relativeURL, baseUrl).toString(); return `href="${absoluteURL}"`; }); body = body.replace(/src="([^"]+)"/g, (match, relativeURL) => { const absoluteURL = new URL(relativeURL, baseUrl).toString(); return `src="${absoluteURL}"`; }); const html = tinyMultipartParser(body); const pdfBuffer = await runPrince(html); return { isBase64Encoded: true, statusCode: 200, headers: { "Content-Type": "application/pdf" }, body: pdfBuffer.toString("base64") }; } catch (err) { console.error('Processing failed:', err); return { statusCode: 500, body: JSON.stringify({ error: err.message }) }; } };
2. 调整Lambda超时时间
通过URL获取HTML+PDF转换的总耗时通常更长,检查并延长Lambda函数的超时时间(建议设置为10-15秒,按需调整),避免因超时导致进程被强制终止。
3. 验证axios响应完整性
在获取HTML后添加日志验证内容长度,确认无截断:
console.log('Fetched HTML length:', response.data.length);
对比直接传HTML的长度,确保内容一致。
4. 检查Prince权限与版本兼容性
确保最新版Prince Lambda包的./prince文件有执行权限,同时验证新版本与Lambda运行环境(如Node.js版本)的兼容性。
内容的提问来源于stack exchange,提问作者Alejandro H
相关产品推荐
相关产品推荐

