Files
monorepo/LCU.API.Internal.FileOperations/LCU.Api.Internal.FileOperations/Services/PdfServices/HtmlToPdfService.cs
T
2026-04-27 10:50:07 -05:00

193 lines
6.7 KiB
C#

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<ValueCollection> 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<TagValue> tagValues)
{
foreach (var tagValue in tagValues)
{
output = output.Replace($"{{{tagValue.Tag}}}", tagValue.Value);
}
return output;
}
public StringBuilder AddCollectionItemsToStringBuilder(List<ValueCollectionItem> 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<ValueCollection> 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);
}
}
}