如何使用C#在AWS Lambda和API Gateway上部署Prince 13.5?

问题描述 投票:0回答:1

我一直按照本文 (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 功能的指南。任何提示、资源或示例代码将不胜感激。预先感谢!

c# aws-lambda deployment api-gateway princexml
1个回答
0
投票

我想出了一个解决方案,我编写了一个包装器来运行 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();
                }
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.