DinkToPdf on linux doesn't show images

735 views Asked by At

I have a .NET 6 Web API project with DinkToPdf which I use on macOS on my dev machine, and two servers on Linux Ubuntu 20.4 and Windows Server 2012. My API detects OS on which it runs and uses the corresponding library to convert HTML to PDF file on output.

My controller:

public class ClientDocController : BaseController
{
    private readonly IClientAppointmentDocumentService _clientAppointmentDocumentService;
    private readonly IConverter _htmlToPdfConverter;

    public ClientDocController(IClientAppointmentDocumentService clientAppointmentDocumentService, IConverter htmlToPdfConverter)
    {
        _clientAppointmentDocumentService = clientAppointmentDocumentService;
        _htmlToPdfConverter = htmlToPdfConverter;
    }
    [HttpGet("{documentId}/pdf/")]
    [RestApiAuthorize(AccountRolePermissions.VIEW_CLIENT_DOCUMENTS)]
    public async Task<IActionResult> GetPdfAsync([FromRoute] int documentId, bool uploadToClientPortal, int? templateId = null, 
        bool clientPrint = false, bool sendToClientEmail = false, CancellationToken cancellationToken = default)
    {
        try
        {
            var htmlDocument = templateId == null
                ? await _clientAppointmentDocumentService.GetDefaultHtmlDocumentAsync(documentId, clientPrint, cancellationToken)
                : await _clientAppointmentDocumentService.GetHtmlDocumentAsync(documentId, templateId, clientPrint, cancellationToken);

            var fileName = $"Document_{documentId}_{DateTime.Now:s}.pdf";
            var conversionSettings = PdfConfigurationDefaults.GetDefaultSettings(htmlDocument); //this get individual settings for each platform
            var pdf = _htmlToPdfConverter.Convert(conversionSettings);
            var result = File(pdf, MediaTypeNames.Application.Pdf, fileName);

            if (sendToClientEmail) await _clientAppointmentDocumentService.SendToClientByEmailAsync(new[] {result});
            if (!uploadToClientPortal) return result;

            var accessToken = Request.Headers["Authorization"].ToString();
            var response = await _clientAppointmentDocumentService.UploadToClientPortalAsync(documentId, result, accessToken);
            return Ok(response);
        }
        catch (Exception e)
        {
            return BadRequest(e.Message);
        }
    }
}

This works well on all machines, although on Linux server there are images not included in resulting PDF under tag <img src="https://..." />.

What I have checked:

  1. This is not SSL problem because if I make this controller to output HTML then images are shown as expected
  2. I have tried every setting (maybe not in all combinations) in conversionSettings without any success
  3. Converting images into base64 string also didn't help. Images didn't shown

Anybody have any ideas, what can I check further?

2

There are 2 answers

0
d-unit On

Had a similar issue on an application hosted on a Linux Ubuntu server and converting image to base 64 worked for me. Put the image in a folder called Resources and used the code below:

byte[] imageArray = File.ReadAllBytes(Path.Combine(Directory.GetCurrentDirectory(), "Resources", "logo.png"));
string base64ImageRepresentation = Convert.ToBase64String(imageArray);

Then the image in the html string:

string.Format("<img src=""data:image/png;base64,{0}"" width=""300"" height=""40"" />", base64ImageRepresentation);

Also had LoadImages set to true on the ObjectSettings:

var objectSettings = new ObjectSettings
{
    WebSettings = { DefaultEncoding = "utf-8", LoadImages = true },
};
var pdf = new HtmlToPdfDocument()
{
    Objects = { objectSettings }
};

Hope this helps!

0
Rahul Sen On

You can convent the image to byte array and then you can use that inside your src

byte[] imageBytes;
using (var webClient = new WebClient())
{
    imageBytes = webClient.DownloadData("https://.....");
}
// OR //
using (var response = await new HttpClient().GetAsync("htp://...."))
{
     imageBytes = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
}
string base64Image = Convert.ToBase64String(imageBytes);
templateBuilder.AppendFormat
   (@"<img src=""data:image/png;base64,{0}"" width=""640"" 
     height=""480"" />", 
     base64Image);