You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 02:20:58