diff --git a/EnvelopeGenerator.Application/DependencyInjection.cs b/EnvelopeGenerator.Application/DependencyInjection.cs index 5eaae3da..ad96bad9 100644 --- a/EnvelopeGenerator.Application/DependencyInjection.cs +++ b/EnvelopeGenerator.Application/DependencyInjection.cs @@ -87,11 +87,13 @@ public static class DependencyInjection services.AddMediatR(cfg => { cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()); + + cfg.AddBehavior(); + cfg.AddBehavior(); #if WINDOWS + cfg.AddBehavior(); cfg.AddBehavior(); #endif - cfg.AddBehavior(); - cfg.AddBehavior(); }); // Add memory cache diff --git a/EnvelopeGenerator.Application/Pdf/Behaviors/AddReportBehavior.cs b/EnvelopeGenerator.Application/Pdf/Behaviors/AddReportBehavior.cs index dc8fadbb..508ad2f4 100644 --- a/EnvelopeGenerator.Application/Pdf/Behaviors/AddReportBehavior.cs +++ b/EnvelopeGenerator.Application/Pdf/Behaviors/AddReportBehavior.cs @@ -39,9 +39,7 @@ public class AddReportBehavior : IPipelineBehavior { var docResult = await next(cancel); - var report = await CreateReport(request.Envelope!, cancel); - - var reportBase64 = Convert.ToBase64String(report); + request.Report = await CreateReport(request.Envelope!, cancel); return docResult; } diff --git a/EnvelopeGenerator.Application/Pdf/Behaviors/CreateHistoryBehavior.cs b/EnvelopeGenerator.Application/Pdf/Behaviors/CreateHistoryBehavior.cs index fb825f22..af65aa82 100644 --- a/EnvelopeGenerator.Application/Pdf/Behaviors/CreateHistoryBehavior.cs +++ b/EnvelopeGenerator.Application/Pdf/Behaviors/CreateHistoryBehavior.cs @@ -34,6 +34,8 @@ public class CreateHistoryBehavior : IPipelineBehavior /// public async Task Handle(BurnPdfCommand request, RequestHandlerDelegate next, CancellationToken cancel) { + var doc = await next(cancel); + if (!request.Debug) await _sender.Send(new CreateHistoryCommand() { @@ -42,6 +44,6 @@ public class CreateHistoryBehavior : IPipelineBehavior Status = EnvelopeStatus.EnvelopeReportCreated, }, cancel); - return await next(cancel); + return doc; } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Pdf/Behaviors/PdfMergeBehavior.cs b/EnvelopeGenerator.Application/Pdf/Behaviors/PdfMergeBehavior.cs new file mode 100644 index 00000000..f901a997 --- /dev/null +++ b/EnvelopeGenerator.Application/Pdf/Behaviors/PdfMergeBehavior.cs @@ -0,0 +1,88 @@ +#if WINDOWS +using EnvelopeGenerator.Application.Common.Extensions; +using EnvelopeGenerator.Application.Exceptions; +using EnvelopeGenerator.Domain.Constants; +using GdPicture14; +using MediatR; + +namespace EnvelopeGenerator.Application.Pdf.Behaviors; + +/// +/// +/// +public class PdfMergeBehavior : IPipelineBehavior +{ + private static readonly bool ALLOW_RASTERIZATION = true; + + private static readonly bool ALLOW_VECTORIZATION = true; + + private static readonly PdfConversionConformance PDFAConformanceLevel = PdfConversionConformance.PDF_A_1b; + + /// + /// + /// + /// + /// + /// + /// + /// + public async Task Handle(BurnPdfCommand request, RequestHandlerDelegate next, CancellationToken cancel) + { + var doc = await next(cancel); + + doc = request.Report is byte[] report + ? MergeDocuments(doc, report) + : throw new InvalidOperationException("The final document report could not be merged." + + "There may be an error related to the behavior register order." + + "Request details:\n" + request.ToJson(Format.Json.ForDiagnostics)); + + string base64String = Convert.ToBase64String(doc); + + return doc; + } + + /// + /// + /// + /// + /// + /// + /// + public static byte[] MergeDocuments(byte[] pDocument, byte[] pReport) + { + using var oDocumentStream = new MemoryStream(pDocument); + using var oReportStream = new MemoryStream(pReport); + using var oFinalStream = new MemoryStream(); + using var oDocumentPDF = new GdPicturePDF(); + using var oReportPDF = new GdPicturePDF(); + GdPictureStatus oStatus = GdPictureStatus.OK; + + // Load the source file into memory + oDocumentPDF.LoadFromStream(oDocumentStream, true); + + oStatus = oDocumentPDF.GetStat(); + if (oStatus != GdPictureStatus.OK) + throw new MergeDocumentException($"Document could not be loaded: {oStatus}"); + + // Load the report file into memory + oReportPDF.LoadFromStream(oReportStream, true); + oStatus = oReportPDF.GetStat(); + if (oStatus != GdPictureStatus.OK) + throw new MergeDocumentException($"Report could not be loaded: {oStatus}"); + + // Merge the documents + var oMergedPDF = oDocumentPDF.Merge2Documents(oDocumentPDF, oReportPDF); + oStatus = oMergedPDF.GetStat(); + if (oStatus != GdPictureStatus.OK) + throw new MergeDocumentException($"Documents could not be merged: {oStatus}"); + + // Convert to PDF/A + oMergedPDF.ConvertToPDFA(oFinalStream, PDFAConformanceLevel, ALLOW_VECTORIZATION, ALLOW_RASTERIZATION); + oStatus = oDocumentPDF.GetStat(); + if (oStatus != GdPictureStatus.OK) + throw new MergeDocumentException($"Document could not be converted to PDF/A: {oStatus}"); + + return oFinalStream.ToArray(); + } +} +#endif \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs b/EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs index 659ee2c8..c50280db 100644 --- a/EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs +++ b/EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs @@ -24,6 +24,10 @@ public record BurnPdfCommand(int? EnvelopeId = null, string? EnvelopeUuid = null internal bool Debug { get; set; } internal Envelope? Envelope { get; set; } + +#if WINDOWS + internal byte[]? Report { get; set; } +#endif } ///