Print Export With Customer header and Footer added

Hello Team,

We are currently using Doconut Core MVC in our application.

When the user clicks the Print
image.png (9.2 KB) button, we will generate a PDF using the following URL:
https://uvexample.com/PagePrint/CreatePdf?token=...&DocumentId=...&from=1&to=4&Paper=A4&Landscape=false

On the server side, we will be using the below method to export the PDF. Can you help us modify the method to achieve our requirement:

[AllowAnonymous]
[HttpGet]
public ActionResult CreatePDF(string token, string DocumentId, string from, string to, string Paper, bool Landscape)
{
try
{
var viewer = GetViewerInstance(token);

    // Export PDF
    byte[] pdf = viewer.ExportToPdf();

    return File(pdf, "application/pdf");
}
catch (Exception ex)
{
    Response.StatusCode = 400;
    return Content("Error exporting PDF: " + ex.Message);
}

}

Requirement

We want to add a custom header and footer to the exported PDF.

  • The header and footer should appear on every page
  • The content may vary based on DocumentId
  • The design is similar to:
    • Header: company/title section
    • Footer: page number / additional info
      refere the attachments for header and footer
      pdf header.jpg (85.5 KB)
      pdf footer.jpg (61.2 KB)

Is there a way to:

  1. Add header and footer directly using Doconut during ExportToPdf() ?
  2. Or is there any recommended approach within Doconut to customize the PDF output?

If not supported natively:

  • What is the recommended way to achieve this while using Doconut?

Any guidance or sample implementation would be very helpful.

Thank you!

@Mohit_Tandel

Thank you for your question.

At the moment, Doconut is primarily a viewer, and the ExportToPdf() method exports the document as-is.
It does not support adding dynamic headers or footers natively during the export process.

We are currently working on expanding these capabilities through a future Editor plugin, but this is not available yet.

Recommended approach

  • Export the PDF using Doconut:
    byte[] pdf = viewer.ExportToPdf();

  • Then post-process the PDF using another library to add custom content.

    [HttpGet]
    public async Task<IActionResult> CreatePdf(string token, long? DocumentId, int from, int to, string Paper, bool Landscape)
    {
        try
        {
            using var memoryStream = new MemoryStream();

            string fileName = $"LTHED_{DateTime.Now:dd-MM-yyyy}.pdf";

            using var document = new Document();

            Rectangle rectangle = Paper switch
            {
                "A0" => PageSize.A0,
                "A1" => PageSize.A1,
                "A2" => PageSize.A2,
                "A3" => PageSize.A3,
                _ => PageSize.A4
            };

            if (Landscape)
                rectangle = rectangle.Rotate();

            document.SetPageSize(rectangle);
            document.SetMargins(0f, 0f, 30f, 30f);

            var writer = PdfWriter.GetInstance(document, memoryStream);
            writer.CloseStream = false;

            // 👉 Get data (use DI instead of new)
            //var printData = _dbContext.SP_DES_GET_UV_Print_Data_Result(DocumentId).FirstOrDefault();

            var param = new SqlParameter("@FileId", DocumentId ?? (object)DBNull.Value);
            var printData = (await _dbContext.SP_DES_GET_UV_Print_Data_Result
                                   .FromSqlRaw("EXEC SP_DES_GET_UV_Print_Data @FileId", param).ToListAsync()).FirstOrDefault();


            if (printData != null && !string.IsNullOrEmpty(printData.DocumentNo))
                fileName = $"UV_{printData.DocumentNo}.pdf";

            writer.PageEvent = new ITextEvents(printData);

            document.Open();

            var request = HttpContext.Request;

            string baseUrl = $"{request.Scheme}://{request.Host}";

            for (int index = from; index <= to; index++)
            {
                string imageUrl = $"{baseUrl}/DocImage.axd?token={token}&zoom=100&page={index}";

                var image = Image.GetInstance(imageUrl);
                float width = rectangle.Width;
                float height = rectangle.Width / image.Width * image.Height;

                if (rectangle.Height - 65 < height)
                {
                    height = rectangle.Height - 65;
                    width = height / image.Height * image.Width;
                }

                image.ScaleToFit(width, height);
                image.Alignment = Element.ALIGN_CENTER;

                var table = new PdfPTable(1)
                {
                    WidthPercentage = 100,
                    HorizontalAlignment = Element.ALIGN_CENTER
                };

                var cell = new PdfPCell(image)
                {
                    HorizontalAlignment = Element.ALIGN_CENTER,
                    VerticalAlignment = Element.ALIGN_MIDDLE,
                    Border = Rectangle.NO_BORDER
                };

                table.AddCell(cell);

                document.Add(table);
            }

            document.Close();

            memoryStream.Position = 0;

            Console.WriteLine($"PDF Size: {memoryStream.Length}");
            var bytes = memoryStream.ToArray();
            return File(bytes, "application/pdf", fileName);
        }
        catch (Exception ex)
        {

            throw;
        }
    }

we have created this method but when calling the URL below, pdf is getting download but inside pdf it shows " you are not authorized to view this page" as show in image
image.png (102.6 KB)

http://localhost:8676/PagePrint/CreatePdf?token=59409e08-9bd9-4c4e-b5e3-6f0c826f9ec9&DocumentId=301234&from=1&to=4&Paper=A4&Landscape=false

kindly help for solving the error

@Mohit_Tandel

What is happening here is related to how Doconut secures document requests.

Doconut protects page image requests through session validation. In your case, the PDF generation code is requesting DocImage.axd from the server side. Although the token is valid, this new request does not carry the original browser session, so Doconut correctly returns an authorization error image.

This is expected behavior and not a document rendering issue.

We recommend updating your implementation so that page images are fetched within the same authorized browser session.

Another option is to use a controlled workaround; you could run Doconut with UnSafeMode = true. However, please note that this disables the session security validation.

Example configurations

For .NET Framework (web.config):

<add key="DoconutUnSafeMode" value="true" />

For .NET Core / .NET 6 and higher:

appBranch.UseDoconut(new DoconutOptions 
{ 
    UnSafeMode = true
});

string imageUrl = $“{baseUrl}/DocImage.axd?token={token}&zoom=100&page={index}”;

is it possible to modify above url to get compressed jpeg format ?

@Mohit_Tandel

Yes, JPEG is supported in the viewer pipeline. For the page image URL, you can append format=jpg or format=jpeg:

string imageUrl = $"{baseUrl}/DocImage.axd?token={token}&zoom=100&page={index}&format=jpg";
  • The main size/quality control exposed here is zoom. Lower zoom gives you a smaller/lower-resolution image. Higher zoom gives better quality but a larger size.

ImageResolution is a viewer/config setting that controls how Doconut renders document pages internally in DPI terms.

This is an example:

var config = new PdfConfig
{
    ImageResolution = 100
};

So in practice:

  • ImageResolution affects the source page render quality.
  • &format=jpg gives you JPEG output.
  • zoom affects the output dimensions returned by DocImage.axd.