Last active
December 20, 2023 08:38
-
-
Save tmakin/d391f446588b040665765b0f7e06c240 to your computer and use it in GitHub Desktop.
c# Html to Pdf on AWS Lambda using AspNetCore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk.Web"> | |
<PropertyGroup> | |
<TargetFramework>netcoreapp3.1</TargetFramework> | |
<AssemblyName>HtmlToPdfAws</AssemblyName> | |
<Rootnamespace>HtmlToPdfAws</Rootnamespace> | |
</PropertyGroup> | |
<ItemGroup> | |
<!-- native assets excluded as we are using lambda layers instead --> | |
<PackageReference Include="Haukcode.WkHtmlToPdfDotNet" Version="1.3.0" ExcludeAssets="native" /> | |
<PackageReference Include="Amazon.Lambda.AspNetCoreServer" Version="5.3.0" /> | |
<PackageReference Include="AWSXRayRecorder.Handlers.AspNetCore" Version="2.7.1" /> | |
</ItemGroup> | |
<ItemGroup> | |
<None Update="Assets\test.html"> | |
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | |
</None> | |
</ItemGroup> | |
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Amazon.Lambda.Core; | |
using Microsoft.AspNetCore.Hosting; | |
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] | |
namespace HtmlToPdfAws | |
{ | |
public class LambdaEntryPoint : Amazon.Lambda.AspNetCoreServer.APIGatewayHttpApiV2ProxyFunction | |
{ | |
protected override void Init(IWebHostBuilder builder) | |
{ | |
builder.UseStartup<Startup>(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.IO; | |
using System.Text; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore.Mvc; | |
using Microsoft.Extensions.Logging; | |
namespace HtmlToPdfAws | |
{ | |
[ApiController] | |
[Route("Pdf")] | |
public class PdfController : ControllerBase | |
{ | |
private readonly ILogger<ExportPdf> _logger; | |
private readonly IPdfGenerator _generator; | |
public ExportPdf(ILogger<ExportPdf> logger, IPdfGenerator generator) | |
{ | |
_logger = logger; | |
_generator = generator; | |
} | |
[HttpPost] | |
public async Task<FileContentResult> Post() | |
{ | |
using var reader = new StreamReader(Request.Body, Encoding.UTF8); | |
var html = await reader.ReadToEndAsync(); | |
return BuildPdfResult(html); | |
} | |
[HttpGet("test")] | |
public async Task<FileContentResult> Get() | |
{ | |
var html = await System.IO.File.ReadAllTextAsync("./Assets/test.html"); | |
return BuildPdfResult(html); | |
} | |
private FileContentResult BuildPdfResult(string html) | |
{ | |
_logger.LogInformation("Processing PDF Request"); | |
var pdf = _generator.BuildPdf(html); | |
_logger.LogInformation($"PDF Generated. Length={pdf.Length}"); | |
return File(pdf, "application/pdf"); | |
} | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using WkHtmlToPdfDotNet; | |
using IPdfConverter = WkHtmlToPdfDotNet.Contracts.IConverter; | |
namespace HtmlToPdfAws | |
{ | |
public interface IPdfGenerator | |
{ | |
byte[] BuildPdf(string html); | |
} | |
internal class PdfGenerator : IPdfGenerator | |
{ | |
private readonly IPdfConverter _pdfConverter = new SynchronizedConverter(new PdfTools()); | |
public byte[] BuildPdf(string html) | |
{ | |
const double margin = 25; | |
return _pdfConverter.Convert(new HtmlToPdfDocument() | |
{ | |
GlobalSettings = { | |
Orientation = Orientation.Portrait, | |
PaperSize = PaperKind.A4, | |
Margins = new MarginSettings(margin, margin, margin, margin), | |
}, | |
Objects = | |
{ | |
new ObjectSettings | |
{ | |
WebSettings = new WebSettings | |
{ | |
PrintMediaType = true, | |
EnableIntelligentShrinking = true | |
}, | |
HtmlContent = html | |
} | |
} | |
}); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Builder; | |
using Microsoft.Extensions.Configuration; | |
using Microsoft.Extensions.DependencyInjection; | |
namespace HtmlToPdfAws | |
{ | |
/// <summary> | |
/// Note that we can't use IStartup interface as it is not supported by the Lambda runtime | |
/// We have to use convention based builders instead | |
/// </summary> | |
public class ExportStartup | |
{ | |
// This method gets called by the runtime. Use this method to add services to the container. | |
public void ConfigureServices(IServiceCollection services) | |
{ | |
// https://andrewlock.net/new-in-asp-net-core-3-service-provider-validation/ | |
services.AddControllers().AddControllersAsServices(); | |
services.AddSingleton<IPdfGenerator, PdfGenerator>(); | |
// ... whatever else you might need | |
} | |
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | |
public void Configure(IApplicationBuilder app) | |
{ | |
app.UseXRay("YourXRayAppName"); | |
app.UseRouting(); | |
app.UseEndpoints(endpoints => | |
{ | |
endpoints.MapControllers(); | |
}); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# SAM deployment template | |
AWSTemplateFormatVersion: '2010-09-09' | |
Transform: AWS::Serverless-2016-10-31 | |
Description: > | |
Demo app for generating pdf from HTML on AWS lamnda using ASP net core | |
Parameters: | |
StageName: | |
Type: String | |
Default: prod | |
Resources: | |
HtmlToPdfAwsApiGateway: # rename this to whatever you like | |
Type: AWS::Serverless::HttpApi | |
Properties: | |
StageName: !Ref StageName | |
FailOnWarnings: True | |
HtmlToPdfAwsFunction: | |
Type: AWS::Serverless::Function # https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction | |
Properties: | |
FunctionName: HtmlToPdfAws | |
Handler: HtmlToPdfAws.LambdaEntryPoint::FunctionHandlerAsync | |
Runtime: dotnetcore3.1 | |
CodeUri: '' # This is injected by 'dotnet lambda deploy-serverless'' | |
MemorySize: 1024 | |
Timeout: 30 | |
Role: !GetAtt HtmlToPdfAwsRole.Arn | |
Policies: | |
- AWSLambdaFullAccess | |
Layers: | |
- arn:aws:lambda:eu-west-2:347599033421:layer:wkhtmltopdf-0_12_6:1 # https://github.com/brandonlim-hs/wkhtmltopdf-aws-lambda-layer | |
- arn:aws:lambda:eu-west-2:347599033421:layer:amazon_linux_fonts:1 # https://github.com/brandonlim-hs/fonts-aws-lambda-layer | |
Environment: | |
Variables: | |
FONTCONFIG_PATH: /opt/etc/fonts | |
Tracing: Active | |
Events: | |
ProxyResource: | |
Type: HttpApi | |
Properties: | |
Path: "/{proxy+}" | |
Method: ANY | |
ApiId: !Ref HtmlToPdfAwsApiGateway | |
HtmlToPdfAwsRole: #https://aws.amazon.com/blogs/compute/sharing-secrets-with-aws-lambda-using-aws-systems-manager-parameter-store/ | |
Type: AWS::IAM::Role | |
Properties: | |
AssumeRolePolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- | |
Effect: Allow | |
Principal: | |
Service: | |
- 'lambda.amazonaws.com' | |
Action: | |
- 'sts:AssumeRole' | |
ManagedPolicyArns: | |
- 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' | |
- 'arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess' | |
- 'arn:aws:iam::aws:policy/AWSLambdaFullAccess' | |
Outputs: | |
ApiURL: | |
Description: API endpoint URL for Prod environment | |
Value: | |
Fn::Sub: https://${HtmlToPdfAwsApiGateway}.execute-api.${AWS::Region}.amazonaws.com/${StageName}/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment