diff --git a/Azure/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions/Function1.cs b/Azure/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions/Function1.cs index c074c6b..7e9409a 100644 --- a/Azure/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions/Function1.cs +++ b/Azure/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions/Function1.cs @@ -5,6 +5,7 @@ using Syncfusion.HtmlConverter; using Syncfusion.Pdf; using Syncfusion.Pdf.Graphics; +using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; @@ -20,58 +21,124 @@ public Function1(ILogger logger) } [Function("Function1")] - public static async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, FunctionContext executionContext) + public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req) { - string blinkBinariesPath = string.Empty; - //Create a new PDF document. - PdfDocument document; - BlinkConverterSettings settings = new BlinkConverterSettings(); - //Creating the stream object. - MemoryStream stream; + _logger.LogInformation("C# HTTP trigger function processed a request."); try { - blinkBinariesPath = SetupBlinkBinaries(); - - //Initialize the HTML to PDF converter with the Blink rendering engine. + byte[] pdfBytes = HtmlToPdfConvert("

Hello world

"); + return new FileStreamResult(new MemoryStream(pdfBytes), "application/pdf"); + } + catch (Exception ex) + { + _logger.LogError(ex.Message.ToString(), "An error occurred while converting HTML to PDF."); + return new ContentResult + { + Content = $"Error: {ex.Message}", + ContentType = "text/plain", + StatusCode = StatusCodes.Status500InternalServerError + }; + + } + + } + public byte[] HtmlToPdfConvert(string htmlText) + { + if (string.IsNullOrWhiteSpace(htmlText)) + { + throw new ArgumentException("HTML text cannot be null or empty.", nameof(htmlText)); + } + + try + { + // Setup Blink binaries and install necessary packages + var blinkBinariesPath = SetupBlinkBinaries(); + InstallLinuxPackages(); + + // Initialize HTML to PDF converter HtmlToPdfConverter htmlConverter = new HtmlToPdfConverter(HtmlRenderingEngine.Blink); - settings.BlinkPath = blinkBinariesPath; - //Assign BlinkConverter settings to the HTML converter + + // Display settings + BlinkConverterSettings settings = new BlinkConverterSettings + { + BlinkPath = blinkBinariesPath, + ViewPortSize = new Syncfusion.Drawing.Size(1024, 768), // Set your desired viewport size + Margin = new PdfMargins + { + Top = 20, // Set your desired margins + Left = 20, + Right = 20, + Bottom = 20 + } + }; htmlConverter.ConverterSettings = settings; - //Convert URL to PDF - document = htmlConverter.Convert("http://www.syncfusion.com"); - stream = new MemoryStream(); - //Save and close the PDF document - document.Save(stream); + + // Convert HTML to PDF + using (var memoryStream = new MemoryStream()) + { + PdfDocument document = htmlConverter.Convert(htmlText, null); + document.Save(memoryStream); + document.Close(true); + return memoryStream.ToArray(); + } + } + catch (Exception ex) + { + // Handle exceptions + Console.WriteLine("An error occurred: " + ex.Message); + throw; + } + } + #region Install dependencies. + private static void InstallLinuxPackages() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return; } - catch(Exception ex) + FileAccessPermissions ExecutableFilePermissions = FileAccessPermissions.UserRead | FileAccessPermissions.UserWrite | FileAccessPermissions.UserExecute | + FileAccessPermissions.GroupRead | FileAccessPermissions.GroupExecute | FileAccessPermissions.OtherRead | FileAccessPermissions.OtherExecute; + string assemblyDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); + //Install the dependencies packages for HTML to PDF conversion in Linux + string shellFilePath = Path.Combine(assemblyDirectory); + string tempBlinkDir = Path.GetTempPath(); + string dependenciesPath = Path.Combine(tempBlinkDir, "dependenciesInstall.sh"); + if (!File.Exists(dependenciesPath)) { - //Create a new PDF document. - document = new PdfDocument(); - //Add a page to the document. - PdfPage page = document.Pages.Add(); - //Create PDF graphics for the page. - PdfGraphics graphics = page.Graphics; - - //Set the standard font. - PdfFont font = new PdfStandardFont(PdfFontFamily.Helvetica, 8); - //Draw the text. - graphics.DrawString(ex.Message.ToString(), font, PdfBrushes.Black, new Syncfusion.Drawing.PointF(0, 0)); - - stream = new MemoryStream(); - //Save the document into memory stream. - document.Save(stream); - + + CopyFilesRecursively(shellFilePath, tempBlinkDir); + var execPath = Path.Combine(tempBlinkDir, "dependenciesInstall.sh"); + if (File.Exists(execPath)) + { + var code = Chmod(execPath, ExecutableFilePermissions); + if (code != 0) + { + throw new Exception("Chmod operation failed"); + } + } + + Process process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "/bin/bash", + Arguments = "-c " + execPath, + CreateNoWindow = true, + UseShellExecute = false, + } + }; + process.Start(); + process.WaitForExit(); } - - document.Close(); - stream.Position = 0; - return new FileStreamResult(stream, "application/pdf"); } - private static string SetupBlinkBinaries( ) + #endregion + + #region Setup Blink Binaries + + private static string SetupBlinkBinaries() { - var fileInfo = new FileInfo(Assembly.GetExecutingAssembly().Location); - string path = fileInfo.Directory.Parent.FullName; - string blinkAppDir = Path.Combine(path, @"wwwroot"); + string assemblyDirectory = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "runtimes", "linux", "native"); + string blinkAppDir = Path.Combine(assemblyDirectory); string tempBlinkDir = Path.GetTempPath(); string chromePath = Path.Combine(tempBlinkDir, "chrome"); if (!File.Exists(chromePath)) @@ -81,6 +148,7 @@ private static string SetupBlinkBinaries( ) } return tempBlinkDir; } + private static void CopyFilesRecursively(string sourcePath, string targetPath) { //Create all the directories from the source to the destination path. @@ -88,25 +156,30 @@ private static void CopyFilesRecursively(string sourcePath, string targetPath) { Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath)); } + //Copy all the files from the source path to the destination path. foreach (string newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories)) { File.Copy(newPath, newPath.Replace(sourcePath, targetPath), true); } } + [DllImport("libc", SetLastError = true, EntryPoint = "chmod")] internal static extern int Chmod(string path, FileAccessPermissions mode); + private static void SetExecutablePermission(string tempBlinkDir) { - FileAccessPermissions ExecutableFilePermissions = FileAccessPermissions.UserRead | FileAccessPermissions.UserWrite | FileAccessPermissions.UserExecute | - FileAccessPermissions.GroupRead | FileAccessPermissions.GroupExecute | FileAccessPermissions.OtherRead | FileAccessPermissions.OtherExecute; + FileAccessPermissions ExecutableFilePermissions = + FileAccessPermissions.UserRead | FileAccessPermissions.UserWrite | FileAccessPermissions.UserExecute | + FileAccessPermissions.GroupRead | FileAccessPermissions.GroupExecute | FileAccessPermissions.OtherRead | + FileAccessPermissions.OtherExecute; string[] executableFiles = new string[] { "chrome", "chrome_sandbox" }; foreach (string executable in executableFiles) { var execPath = Path.Combine(tempBlinkDir, executable); if (File.Exists(execPath)) { - var code = Function1.Chmod(execPath, ExecutableFilePermissions); + var code = Chmod(execPath, ExecutableFilePermissions); if (code != 0) { throw new Exception("Chmod operation failed"); @@ -114,6 +187,7 @@ private static void SetExecutablePermission(string tempBlinkDir) } } } + [Flags] internal enum FileAccessPermissions : uint { @@ -127,5 +201,7 @@ internal enum FileAccessPermissions : uint UserWrite = 128, UserRead = 256 } + + #endregion } } diff --git a/Azure/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions.csproj b/Azure/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions.csproj index 8bc7edb..99b1a3a 100644 --- a/Azure/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions.csproj +++ b/Azure/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions.csproj @@ -17,11 +17,14 @@ + + Always + PreserveNewest - PreserveNewest + Always Never diff --git a/Azure/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions/dependenciesInstall.sh b/Azure/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions/dependenciesInstall.sh new file mode 100644 index 0000000..01aab92 --- /dev/null +++ b/Azure/HTML_to_PDF_Azure_functions/HTML_to_PDF_Azure_functions/dependenciesInstall.sh @@ -0,0 +1 @@ +apt-get update && apt-get install -yq --no-install-recommends libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 libnss3 libgbm1 \ No newline at end of file