如何使用C#在AWS Lambda与API Gateway部署Prince 13.5?
用C#在AWS Lambda + API Gateway部署Prince 13.5指南
一、准备工作
- 下载Prince 13.5的Linux x86_64版本(Lambda运行在Amazon Linux环境),解压后提取核心执行文件和依赖库
- 安装.NET 6 SDK(Lambda支持的长期支持版本)
- 安装AWS Toolkit for Visual Studio(方便快速创建Lambda项目)
二、搭建Lambda函数(C#)
创建Lambda项目
- 在Visual Studio中选择「AWS Lambda Project (.NET Core C#)」,模板选「Empty Function」
- 项目命名示例:
PrincePdfGenerator
整合Prince文件
- 将Prince的执行文件(
prince)和依赖库(lib目录下的所有文件)复制到项目根目录,设置文件属性为「复制到输出目录:始终复制」 - 注意:Lambda的工作目录无执行权限,必须将Prince文件复制到临时目录
/tmp后再执行
- 将Prince的执行文件(
核心代码实现
using System; using System.IO; using System.Diagnostics; using System.Collections.Generic; using Amazon.Lambda.Core; using Amazon.Lambda.APIGatewayEvents; [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] namespace PrincePdfGenerator { public class Function { public APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context) { try { // 复制Prince文件到/tmp并获取执行路径 var princeExecPath = CopyPrinceToTempDir(); // 从API请求Body读取HTML内容 var htmlContent = request.Body; var inputHtmlPath = Path.Combine(Path.GetTempPath(), "input.html"); File.WriteAllText(inputHtmlPath, htmlContent); // 定义输出PDF路径 var outputPdfPath = Path.Combine(Path.GetTempPath(), "output.pdf"); // 构造Prince执行命令 var processStartInfo = new ProcessStartInfo { FileName = princeExecPath, Arguments = $"--no-warn {inputHtmlPath} -o {outputPdfPath}", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; // 执行Prince命令 using var process = Process.Start(processStartInfo); process.WaitForExit(); if (process.ExitCode != 0) { var errorMsg = process.StandardError.ReadToEnd(); return new APIGatewayProxyResponse { StatusCode = 500, Body = $"Prince执行失败: {errorMsg}", Headers = new Dictionary<string, string> { { "Content-Type", "text/plain" } } }; } // 读取PDF并返回Base64编码结果 var pdfBytes = File.ReadAllBytes(outputPdfPath); var base64Pdf = Convert.ToBase64String(pdfBytes); return new APIGatewayProxyResponse { StatusCode = 200, Body = base64Pdf, Headers = new Dictionary<string, string> { { "Content-Type", "application/pdf" }, { "Content-Disposition", "attachment; filename=output.pdf" } }, IsBase64Encoded = true }; } catch (Exception ex) { return new APIGatewayProxyResponse { StatusCode = 500, Body = $"服务器错误: {ex.Message}", Headers = new Dictionary<string, string> { { "Content-Type", "text/plain" } } }; } } private string CopyPrinceToTempDir() { var tmpDir = Path.GetTempPath(); var princeExecDest = Path.Combine(tmpDir, "prince"); // 复制执行文件并赋予执行权限 if (!File.Exists(princeExecDest)) { var princeExecSrc = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "prince"); File.Copy(princeExecSrc, princeExecDest); Process.Start("chmod", $"+x {princeExecDest}").WaitForExit(); } // 复制依赖库到/tmp/lib var libSrcDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "lib"); var libDestDir = Path.Combine(tmpDir, "lib"); if (!Directory.Exists(libDestDir)) { Directory.CreateDirectory(libDestDir); foreach (var file in Directory.GetFiles(libSrcDir)) { var destFile = Path.Combine(libDestDir, Path.GetFileName(file)); if (!File.Exists(destFile)) File.Copy(file, destFile); } } // 设置环境变量让Prince找到依赖库 Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", $"{libDestDir}:{Environment.GetEnvironmentVariable("LD_LIBRARY_PATH")}"); return princeExecDest; } } }
三、打包部署
- 在Visual Studio右键项目,选择「Publish to AWS Lambda」
- 配置Lambda参数:运行时选
.NET 6,内存建议设置为1024MB及以上(Prince生成PDF需要较多内存),超时设置为30秒(可根据PDF复杂度调整) - 注意:部署包需包含Prince文件,确保压缩后不超过50MB、解压后不超过250MB(Lambda的包大小限制)
四、API Gateway集成
- 创建REST API
- 在AWS控制台的API Gateway中创建REST API,选择「New API」
- 添加资源与方法
- 添加
/generate-pdf资源,创建POST方法,集成类型选「Lambda Function」,关联刚才部署的Lambda函数
- 添加
- 配置请求响应
- 在POST方法的「Integration Request」中,设置「Content Handling」为「Passthrough」
- 在「Method Response」中,添加200状态码,设置响应头
Content-Type为application/pdf、Content-Disposition为attachment; filename=output.pdf
- 部署API
- 创建部署阶段(如prod),获取调用URL即可测试
五、关键技巧
- 权限处理:Lambda默认拥有
/tmp目录的读写权限,无需额外配置 - 依赖库路径:必须设置
LD_LIBRARY_PATH指向/tmp/lib,否则Prince会因找不到依赖库执行失败 - 资源调优:复杂PDF生成需调高内存和超时时间,可通过CloudWatch日志监控执行情况
- 日志调试:通过CloudWatch Logs查看Lambda的执行日志,快速定位Prince的报错信息
内容的提问来源于stack exchange,提问作者Steve Shahbazi
相关产品推荐
相关产品推荐

