我一直按照本文 (https://medium.com/@bruce_39084/setting-up-prince-on-aws-lambda-and-api-gateway-4d524dcb035b) 中概述的步骤部署 Prince 13.5在AWS Lambda和API Gateway上,但提供的部署包是基于Node.js的。我更喜欢使用 C#,所以我想知道是否有人对如何使用 C# 创建类似的部署包有深入的了解?具体来说,我正在寻找有关如何设置 Lambda 函数、将其与 API Gateway 集成以及使用 C# 处理 Prince 功能的指南。任何提示、资源或示例代码将不胜感激。预先感谢!
我想出了一个解决方案,我编写了一个包装器来运行 Prince:
using System;
using System.IO;
using System.Text;
using System.Diagnostics;
using Amazon.Lambda.Core;
using Amazon.Lambda.APIGatewayEvents;
using System.Collections.Generic;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace cSharpPrinceLambda
{
public class Function
{
public APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
{
if (request?.Body == null)
{
return new APIGatewayProxyResponse
{
StatusCode = 400,
Body = "No data."
};
}
string body = request.Body;
if (request.IsBase64Encoded)
{
byte[] data = Convert.FromBase64String(body);
body = Encoding.UTF8.GetString(data);
}
string html;
try
{
html = TinyMultipartParser(body);
}
catch (Exception ex)
{
return new APIGatewayProxyResponse
{
StatusCode = 500,
Body = ex.Message
};
}
byte[] pdfBytes;
try
{
pdfBytes = GeneratePdf(html);
}
catch (Exception ex)
{
return new APIGatewayProxyResponse
{
StatusCode = 500,
Body = ex.Message
};
}
return new APIGatewayProxyResponse
{
IsBase64Encoded = true,
StatusCode = 200,
Headers = new Dictionary<string, string> { { "Content-Type", "application/pdf" } },
Body = Convert.ToBase64String(pdfBytes)
};
}
private string TinyMultipartParser(string data)
{
var lines = data.Split(new[] { "\r\n" }, StringSplitOptions.None);
var boundary = lines[0];
var endboundary = boundary + "--";
var htmlContent = new StringBuilder();
bool inBody = false;
bool isHtmlPart = false;
foreach (var line in lines)
{
if (line.Contains(boundary))
{
inBody = false;
isHtmlPart = false;
continue;
}
if (line.Contains(endboundary))
{
break;
}
if (line.StartsWith("Content-Type: text/html", StringComparison.OrdinalIgnoreCase))
{
isHtmlPart = true;
continue;
}
if (isHtmlPart && string.IsNullOrWhiteSpace(line))
{
inBody = true;
continue;
}
if (inBody)
{
htmlContent.AppendLine(line);
}
}
if (htmlContent.Length == 0)
{
throw new Exception("Failed to parse HTML content.");
}
return htmlContent.ToString().Trim();
}
private byte[] GeneratePdf(string html)
{
var startInfo = new ProcessStartInfo
{
FileName = "./prince-20240523/prince",//I've made a new folder in my project called prince-20240523 and put the prince version for AWS there, please note that you need to modify the fontconfig as well
Arguments = "- -o -",
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
using (var process = new Process { StartInfo = startInfo })
{
process.Start();
using (var stdin = process.StandardInput)
{
stdin.Write(html);
}
using (var memoryStream = new MemoryStream())
{
process.StandardOutput.BaseStream.CopyTo(memoryStream);
var errorOutput = process.StandardError.ReadToEnd();
if (!process.WaitForExit(10000) || process.ExitCode != 0)
{
throw new Exception(errorOutput);
}
return memoryStream.ToArray();
}
}
}
}
}