1

I created an Azure function to do HTML to Pdf conversion and am getting the following error in Azure function logs:

Access to the path 'C:\Program Files (x86)\SiteExtensions\Functions\3.20.0\32bit\wkhtmltopdf' is denied.

Code on the functions is pretty basic:

var htmlToPdf = new NReco.PdfGenerator.HtmlToPdfConverter();
        
var pdfBytes = htmlToPdf.GeneratePdf(req.BodyHtml);

return new FileContentResult(pdfBytes, "application/pdf")
    {
        FileDownloadName = "test.pdf"
    };

Any help would be greatly appreciated

The same code works in Visual Studio debug locally

error stack:

Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while executing function: HTMLtoPdfConverter ---> System.UnauthorizedAccessException: Access to the path 'C:\Program Files (x86)\SiteExtensions\Functions\3.20.0\32bit\wkhtmltopdf' is denied. at System.IO.FileSystem.CreateDirectory(String fullPath, Byte[] securityDescriptor) at System.IO.Directory.CreateDirectory(String path) at NReco.PdfGenerator.HtmlToPdfConverter.EnsureWkHtmlLibs() at NReco.PdfGenerator.HtmlToPdfConverter.GeneratePdfInternal(WkHtmlInput[] htmlFiles, String inputContent, String coverHtml, String outputPdfFilePath, Stream outputStream) at NReco.PdfGenerator.HtmlToPdfConverter.GeneratePdf(String htmlContent, String coverHtml, Stream output) at NReco.PdfGenerator.HtmlToPdfConverter.GeneratePdf(String htmlContent, String coverHtml) at NReco.PdfGenerator.HtmlToPdfConverter.GeneratePdf(String htmlContent) at Showcast.Azure.Functions.HTMLtoPdfConverter.Run(HtmlToPdfConverterArgs req, ILogger log) in C:\Showcast\Code\showcast.web\Showcast.Azure.Functions\HTMLtoPdfConverter.cs:line 26 at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.InvokeAsync(Object instance, Object[] arguments) in D:\a_work\1\s\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.cs:line 52 at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeWithTimeoutAsync(IFunctionInvoker invoker, ParameterHelper parameterHelper, CancellationTokenSource timeoutTokenSource, CancellationTokenSource functionCancellationTokenSource, Boolean throwOnTimeout, TimeSpan timerInterval, IFunctionInstance instance) in D:\a_work\1\s\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 581 at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithWatchersAsync(IFunctionInstanceEx instance, ParameterHelper parameterHelper, ILogger logger, CancellationTokenSource functionCancellationTokenSource) in D:\a_work\1\s\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 527 at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(IFunctionInstanceEx instance, FunctionStartedMessage message, FunctionInstanceLogEntry instanceLogEntry, ParameterHelper parameterHelper, ILogger logger, CancellationToken cancellationToken) in D:\a_work\1\s\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 306 --- End of inner exception stack trace --- at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(IFunctionInstanceEx instance, FunctionStartedMessage message, FunctionInstanceLogEntry instanceLogEntry, ParameterHelper parameterHelper, ILogger logger, CancellationToken cancellationToken) in D:\a_work\1\s\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 352 at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsync(IFunctionInstance functionInstance, CancellationToken cancellationToken) in D:\a_work\1\s\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 108

doctorlove
  • 18,872
  • 2
  • 46
  • 62
Angelo
  • 35
  • 6
  • please share your whole code to help you better – Ikhtesam Afrin Aug 22 '23 at 08:38
  • [FunctionName("HTMLtoPdfConverter")] public static async Task Run( [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HtmlToPdfConverterArgs req, ILogger log) { var htmlToPdf = new NReco.PdfGenerator.HtmlToPdfConverter(); var pdfBytes = htmlToPdf.GeneratePdf(req.BodyHtml); return new FileContentResult(pdfBytes, "application/pdf") { FileDownloadName = "test.pdf" }; } – Angelo Aug 22 '23 at 09:01
  • what does HtmlToPdfConverterArgs contains in your case – Ikhtesam Afrin Aug 22 '23 at 09:20
  • it's a class containing 3 string properties – Angelo Aug 22 '23 at 09:27
  • your function works locally? or you are getting this error in local? – Ikhtesam Afrin Aug 22 '23 at 09:31

1 Answers1

0

This error

Access to the path 'C:\Program Files (x86)\SiteExtensions\Functions\3.20.0\32bit\wkhtmltopdf' is denied.

indicates that you use "NReco.PdfGenerator" nuget which includes wkhtmltopdf binaries for Windows and it tries to extract them on the first GeneratePdf method call but default location for this binaries (which is usually app's folder with DLLs) is not accessible for write.

To fix this it is enough to specify another location for wkhtmltopdf binaries, in most cases temp folder is accessible for write and can be used for this purpose:

var htmlToPdf = new NReco.PdfGenerator.HtmlToPdfConverter();
htmlToPdf.PdfToolPath = Path.Combine( Path.GetTempPath(), "wkhtmltopdf" );
Vitaliy Fedorchenko
  • 8,447
  • 3
  • 37
  • 34
  • Hi Vitaliy, thank you for the help. With the above change, I am not getting an error on Azure but the generated PDF has just a few black squares instead of the actual text that I passed to it. – Angelo Aug 22 '23 at 23:03
  • @Angelo Black squares may indicate that your HTML template uses font that is missed on Azure Function environment. If this is standard Windows font (like Arial) it might be possible that your HTML may use non-English unicode letters and default system font simply don't have glyphs for these letters. – Vitaliy Fedorchenko Aug 24 '23 at 07:27
  • you are right. it was the missing fonts. I scaled up the Azure Function app to a higher plan and it works great now. Thank you very much. – Angelo Aug 25 '23 at 12:33