Search code examples
javascriptc#asp.netpdfpdf-generation

QuestPDF does not save the PDF and does not open on a new tab


Iam using QuestPDF in asp.net core web application. PDF is looking good and has everything it should. The issue is it is not displaying in the browser but rather in acrobat reader or anything similar when I use .GeneratePdfAndShow() When I use .GeneratePdf() It does not show at all I need the document to be showed to the user preferably in a new tab as a PDF so they can print and move on inside the application

The issue is I cannot call the Print() function from JS if I could I would just say on the success window.open _blank But I need to call the Print() function from another action point Iam doing it like so:

  if (newKanbanItems.Any())
 {
     List<Object> KanbanOBJS = new List<Object>();
     foreach (var item in newKanbanItems) 
     {
         int position = _db.ListContentCST.FirstOrDefault(x => x.LCCST_Id == item.KL_ListContentId).LCCST_Position;
         Object KanbanOBJ = new
         {
             LCCST_Position = position,
             PagodaPlace = item.KL_PagodaPlace,
             Leadset = item.KL_Material,
             QtyOfBundles = item.KL_QtyOfBundles
         };
         KanbanOBJS.Add(KanbanOBJ);
     }
     Print(area, userCST, name, KanbanOBJS);
 }

I need to call it from the Backend because I can than go thru a loop to get all of the objects I need to print:

 // Inserting the Table right after the row
 column.Item()
 .PaddingTop(3)
 .Table(table =>
 {
     table.ColumnsDefinition(columns =>
     {
         columns.RelativeColumn();
         columns.RelativeColumn();
         columns.RelativeColumn();
         columns.RelativeColumn();
         columns.RelativeColumn();
     });
     table.Header(header =>
     {
         header.Cell()
         .Border(6, unit: Unit.Mil)
         .AlignCenter()
         .AlignMiddle()
         .Text("LCCST_Position");
         header.Cell()
         .Border(6, unit: Unit.Mil)
         .AlignCenter()
         .AlignMiddle()
         .Text("Pagoda Place");
         header.Cell()
         .Border(6, unit: Unit.Mil)
         .AlignCenter()
         .AlignMiddle()
         .Text("Leadset");
         header.Cell()
         .Border(6, unit: Unit.Mil)
         .AlignCenter()
         .AlignMiddle()
         .Text("Quantity of Bundles");
         header.Cell()
         .Border(6, unit: Unit.Mil)
         .AlignCenter()
         .AlignMiddle()
         .Text("Commisioned?");
     });
     foreach (var item in KanbanOBJ)
     {
         dynamic obj = item;
         table.Cell()
         .AlignCenter()
         .AlignMiddle()
         .Text($"{obj.LCCST_Position}");
         table.Cell()
         .AlignCenter()
         .AlignMiddle()
         .Text($"{obj.PagodaPlace}");
         table.Cell()
         .AlignCenter()
         .AlignMiddle()
         .Text($"{obj.Leadset}");
         table.Cell()
         .AlignCenter()
         .AlignMiddle()
         .Text($"{obj.QtyOfBundles}");
         table.Cell()
         .AlignCenter()
         .AlignMiddle()
         .Text("");
     }

 });

Does anyone have any workaround ?

I tried every QuestPDF .Generate() methods I tried to ask ChatGPT about the issue and checked the QuestPDF documentation haven't found anything helpful

The file cannot be saved locally it needs to be opened in the browser


Solution

  • I have solved this issue via a few steps esentially im using blob to display the PDF in the frontend and im saving my PDF to base64String

    Steps

    fetching my data back to the fronted:

    if (newKanbanItems.Any())
    {
        List<KanbanItem> KanbanOBJS = new List<KanbanItem>();
        foreach (var item in newKanbanItems)
        {
            int position = _db.ListContentCST.FirstOrDefault(x => x.LCCST_Id == item.KL_ListContentId).LCCST_Position;
            KanbanItem KanbanOBJ = new()
            {
                LCCST_Position = position,
                PagodaPlace = item.KL_PagodaPlace,
                Leadset = item.KL_Material,
                QtyOfBundles = item.KL_QtyOfBundles
            };
            KanbanOBJS.Add(KanbanOBJ);
        }
        return new JsonResult(new { success = true, message = listSaved, listId = name, KanbanOBJ = KanbanOBJS });
    

    Than I call a frontend function in my success that executes the print:

     success: function (result) {
         if (result.success) {
             displaySuccessMessage(result.message, "");
             listCSTTable.ajax.reload();
    
             generateAndOpenPdf(result.listId, result.KanbanOBJ);
             
         }
         else {
             displayErrorMessage(result.message, "");
             listCSTTable.ajax.reload();
         }
     }
    

    The PrintCall:

    function generateAndOpenPdf(listId, KanbanOBJ) {
        var area = "@area";
        var userCST = "@CSTUser";
        var printUrl = "@Url.Action("Print", "ScannerCST")";
    
        $.ajax({
            type: "POST",
            url: printUrl,
            data: JSON.stringify({ Area: area, User: userCST, ListId: listId, KanbanOBJ: KanbanOBJ }),
            contentType: "application/json; charset=utf-8",
            success: function (result) {
                if (result.success && result.pdfBase64) {
                    var pdfData = atob(result.pdfBase64);
                    var arrayBuffer = new Uint8Array(pdfData.length);
                    for (var i = 0; i < pdfData.length; i++) {
                        arrayBuffer[i] = pdfData.charCodeAt(i);
                    }
                    var blob = new Blob([arrayBuffer], { type: "application/pdf" });
                    var url = URL.createObjectURL(blob);
                    window.open(url, '_blank');
                } else {
                    console.error("PDF generation failed or no base64 string provided.");
                }
            },
           
        });
    }
    

    And finally I have changed the print to Generate the pdf into base64String and encode it in a success in the frontend:

    public async Task<IActionResult> Print([FromBody] PrintKanban model)
    
    {
        QuestPDF.Settings.License = LicenseType.Community;
        var stream = new MemoryStream();
        Document.Create(document =>
        {
            //Document creation here
        }).GeneratePdf(stream);
        stream.Position = 0;
        var bytes = stream.ToArray();
        var base64String = Convert.ToBase64String(bytes);
    
        return Json(new { success = true, pdfBase64 = base64String });
    }