using System; using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Serilog; using Newtonsoft.Json; using LCU.Library.Internal.Exceptions; using LCU.Library.Internal.FileOperationsModels.Models.HtmlToPdfModels; using LCU.Api.Internal.FileOperations.Configurations; using System.Threading; namespace LCU.Api.Internal.FileOperations.Services.PdfServices; public class HtmlToPdfService : IHtmlToPdfService { private readonly ApiConfiguration _apiConfiguration; private readonly IDirectFileService _directFileService; public HtmlToPdfService(ApiConfiguration apiConfiguration, IDirectFileService directFileService) { _apiConfiguration = apiConfiguration; _directFileService = directFileService; } public byte[] ConvertHtmlToPdf(HtmlToPdfRequest htmlToPdfRequest) { try { var output = CreateHtmlOutput(htmlToPdfRequest); var finalOutput = CleanUpUnusedTagsFromOutput(output); File.WriteAllText($"{htmlToPdfRequest.FinalHtmlSaveFilePath}{htmlToPdfRequest.PdfName}.html", finalOutput); var fileCreated = CreatePdfFromHtml(htmlToPdfRequest); if (!fileCreated) { throw new ServiceException($"Pdf file was not created. HtmlToPdfRequest: {JsonConvert.SerializeObject(htmlToPdfRequest)}"); } var pdfBytes = _directFileService.GetFileBytes(htmlToPdfRequest.FinalPdfSaveFilePathWithFile); CleanUpHtmlAndPdfFiles(htmlToPdfRequest); return pdfBytes; } catch (Exception exception) { var message = "Failure to Convert Html To Pdf."; Log.Error(exception, $"{message} HtmlToPdfRequest:{JsonConvert.SerializeObject(htmlToPdfRequest)}"); throw new ServiceException($"{message}. ExceptionMessage:{exception.Message}"); } } public string CreateHtmlOutput(HtmlToPdfRequest htmlToPdfRequest) { var templateOutput = AddBodyValuesToTemplateOutput(htmlToPdfRequest); templateOutput = BuildOutputFromCollectionValues(htmlToPdfRequest.BodyValueCollections, templateOutput); return templateOutput; } public string AddBodyValuesToTemplateOutput(HtmlToPdfRequest htmlToPdfRequest) { var templateOutput = File.ReadAllText(htmlToPdfRequest.HtmlTemplateFilePath); templateOutput = AddTagValuesToOutput(templateOutput, htmlToPdfRequest.BodyTagValues); return templateOutput; } public string BuildOutputFromCollectionValues(List valueCollections, string output) { if (valueCollections == null || !valueCollections.Any()) { return output; } foreach (var bodyValueCollection in valueCollections) { var rowTemplateOutput = File.ReadAllText(bodyValueCollection.CollectionHtmlTemplateFilePath); var rowsBuilder = new StringBuilder(); rowsBuilder = AddCollectionItemsToStringBuilder(bodyValueCollection.ValueCollectionItems, rowTemplateOutput, rowsBuilder); output = output.Replace($"{{{bodyValueCollection.CollectionTag}}}", rowsBuilder.ToString()); } return output; } public string AddTagValuesToOutput(string output, List tagValues) { foreach (var tagValue in tagValues) { output = output.Replace($"{{{tagValue.Tag}}}", tagValue.Value); } return output; } public StringBuilder AddCollectionItemsToStringBuilder(List valueCollectionItems, string output, StringBuilder builder) { foreach (var valueCollectionItem in valueCollectionItems) { var tempOutput = output; tempOutput = AddTagValuesToOutput(tempOutput, valueCollectionItem.TagValues); if (valueCollectionItem.ValueCollections != null && valueCollectionItem.ValueCollections.Any()) { tempOutput = BuildItemValueCollectionsOutput(valueCollectionItem.ValueCollections, tempOutput); } builder.Append(tempOutput); } return builder; } public string BuildItemValueCollectionsOutput(List valueCollections, string templateOutput) { if (valueCollections == null) { return templateOutput; } templateOutput = BuildOutputFromCollectionValues(valueCollections, templateOutput); return templateOutput; } public string CleanUpUnusedTagsFromOutput(string output) { var pattern = @"{[A-Za-z0-9]*}"; var finalOutput = Regex.Replace(output, pattern, string.Empty); return finalOutput; } public void SaveHtmlToFilePath(HtmlToPdfRequest htmlToPdfRequest, string htmlOutput) { using (StreamWriter outputFile = new StreamWriter($"{htmlToPdfRequest.FinalHtmlSaveFilePath}{htmlToPdfRequest.PdfName}.html")) { outputFile.Write(htmlOutput); } } public bool CreatePdfFromHtml(HtmlToPdfRequest htmlToPdfRequest) { try { var url = $"{htmlToPdfRequest.FinalHtmlSaveFilePath}{htmlToPdfRequest.PdfName}.html"; var output = Path.Combine(htmlToPdfRequest.FinalPdfSaveFilePath, $"{htmlToPdfRequest.PdfName}.pdf"); using (var process = new Process()) { process.StartInfo.FileName = _apiConfiguration.ChromePath; process.StartInfo.Arguments = $"--user-data-dir={_apiConfiguration.FileOperationsChromeProfileFolderPath} " + $"--headless --disable-gpu --print-to-pdf={output} {url} --no-pdf-header-footer"; process.Start(); process.WaitForExit(); } var attempts = 0; var fileCreated = false; while (!fileCreated) { fileCreated = File.Exists(htmlToPdfRequest.FinalPdfSaveFilePathWithFile); attempts++; if (attempts > _apiConfiguration.MaxFileCheckAttempts) { break; } Thread.Sleep(1000); } return fileCreated; } catch (Exception exception) { var message = $"Failure to Create Pdf From Html."; Log.Error(exception, message); throw new Exception($"{message}. Exception Message: {exception.Message}"); } } public void CleanUpHtmlAndPdfFiles(HtmlToPdfRequest htmlToPdfRequest) { if (!htmlToPdfRequest.KeepHtmlFile) { File.Delete(htmlToPdfRequest.FinalHtmlSaveFilePathWithFile); } if (!htmlToPdfRequest.KeepPdfFile) { File.Delete(htmlToPdfRequest.FinalPdfSaveFilePathWithFile); } } }