3

I have a pdf invoice created using .Net Core 3 Web API and DinkToPdf library.

Now I need to insert into pdf an image as signature. I created the Resource folder of my project and add the image with the Copy to Output Directory set to allways. But I don't know how to use it in my string value which contain all the pdf data.

 var htmlDoc = new StringBuilder();
 ...
 htmlDoc.AppendLine("<td>");

 // here I need to insert the image
 Stream imgStream = Assembly.GetExecutingAssembly()
  .GetManifestResourceStream("Project.Resources.signature.jpeg"); // is allways null
 or
 htmlDoc.AppendLine("<img src=\"Project.Resources.signature.jpeg\" />");

 htmlDoc.AppendLine("</td>");

 var doc = new HtmlToPdfDocument()
 {
     GlobalSettings = {
         ColorMode = ColorMode.Color,
         Orientation = Orientation.Landscape,
         PaperSize = PaperKind.A4Plus,
         Margins = new MarginSettings() { Top = 10, Left = 30, Right = 30 }
     },
     Objects = {
         new ObjectSettings() {
             PagesCount = true,
             HtmlContent = htmlDoc.ToString(),
             WebSettings = { DefaultEncoding = "utf-8" }
         }
     }
 };

 var pdf = converter.Convert(doc);
 var stream = new MemoryStream(pdf);
 var contentType = @"application/pdf";
 var fileName = $"Invoice_{entity.Id}.pdf";
 stream.Seek(0, SeekOrigin.Begin);
 
 return File(stream, contentType, fileName);

Startup.cs:

services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));

edit: I found absolute path works

 htmlDoc.AppendLine("<img src=\"C/User/Application/Project/Resources/signature.jpeg\" />");

But, this is not an optimal solution because the absolute path of local environment is different of production environment .

any other idea? thanks

AlleXyS
  • 2,476
  • 2
  • 17
  • 37

1 Answers1

1

The working directory of Asp.net Core is different from the web directory. You need to add the folder wwwroot in the project root directory. It is the root directory of the web.

enter image description here

In controller, get the project root directory through IWebHostEnvironment. Here is the example.

[ApiController]
[Route("dink/")]
public class DinkController:ControllerBase
{
    IConverter converter;
    public IConfiguration Configuration;
    IWebHostEnvironment webHostEnvironment;
    public DinkController(IConverter _converter,IConfiguration configuration,IWebHostEnvironment environment)
    {
        converter = _converter;
        Configuration = configuration;
        webHostEnvironment = environment;
    }
    //[Route("get")]
    public IActionResult get()
    {
        var htmlDoc = new StringBuilder();
        htmlDoc.AppendLine("<td>");
        var path = webHostEnvironment.WebRootPath+"\\1.png";//It fetches files under wwwroot
        htmlDoc.AppendLine($"<img src=\"{path}\" />");
        htmlDoc.AppendLine("</td>");

        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                 ColorMode = ColorMode.Color,
                 Orientation = Orientation.Landscape,
                 PaperSize = PaperKind.A4Plus,
                 Margins = new MarginSettings() { Top = 10, Left = 30, Right = 30 }
             },
             Objects = {
                 new ObjectSettings() {
                     PagesCount = true,
                     HtmlContent = htmlDoc.ToString(),
                     WebSettings = { DefaultEncoding = "utf-8" }
                 }
             }
        };

        var pdf = converter.Convert(doc);
        var stream = new MemoryStream(pdf);
        var contentType = @"application/pdf";
        var fileName = $"Invoice_Id.pdf";
        stream.Seek(0, SeekOrigin.Begin);

        return File(stream, contentType, fileName);
    }
}
Karney.
  • 4,803
  • 2
  • 7
  • 11
  • Thanks for your answer. The problem is that I need to use DinktoPdf into a service, which is an external project (dll dependency for my API) and I can't use IWebHostEnvironment there because Startup.cs doesn't exists. – AlleXyS Nov 08 '20 at 18:59
  • Do you have wwwroot folder? Because the service can still provide an interface, you can pass parameters to it when you reference it in the controller. – Karney. Nov 12 '20 at 03:16