'problem showing PDF in Blazor page from byte array

I have gone through all the suggestions for how to take a byte array stored in SQL Server db as varbinary and display it as PDF in a Blazor website. I'm successful in ASP.Net with the aspx pages and code behind but I can't seem to find the right combination for Blazor (ShowPDF.razor and code behind ShowPDF.razor.cs)

Here is what I have as variants in the code behind:

  1. The aReport.ReportDocument is returning a byte array of aReport.DocumentSize from the DB

     FileStreamResult GetPDF()
     {
         var pdfStream = new System.IO.MemoryStream();
         this.rdb = new ReportData();
         aReport = rdb.GetWithReport(1);
    
         pdfStream.Write(aReport.ReportDocument, 0, aReport.DocumentSize);
         pdfStream.Position = 0;
         return new FileStreamResult(pdfStream, new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("application/pdf"));
     }
    

OR 2. direct binary array to base 64 encoding:

return Convert.ToBase64String(aReport.ReportDocument);

While those two processes return the data, I'm unable to find how to set up the razor page to show the result. I have tried:

<object src="@Url.Action("GetPDF")"/> 

and other variants without success.

Thanks!



Solution 1:[1]

I'm afraid this solution is not optimal for medium size or large PDF files. Nobody sets systematically image source as base64 string. It should be the same for PDF files. Browsers will appreciate downloading PDF in a separate thread not in the HTML code rendering.

In Blazor, this can be easy achieved using a custom middleware.

namespace MyMiddlewares
{
    public class ShowPdf
    {
        public ShowPdf(RequestDelegate next)
        {
            //_next = next; no call to _next.Invoke(context) because the handler is at the end of the request pipeline, so there will be no next middleware to invoke.
        }

        public async Task Invoke(HttpContext context)
        {
            byte[] pdfBytes = getPdfFromDb(context.Request.Query["pdfid"]);
            context.Response.ContentType = "application/pdf";

            context.Response.Headers.Add("Content-Disposition",
                                "attachment; " +
                                "filename=\"mypdf.pdf\"; " +
                                "size=" + pdfBytes.Length + "; " +
                                "creation-date=" + DateTime.Now.ToString("R").Replace(",", "") + "; " +
                                "modification-date=" + DateTime.Now.ToString("R").Replace(",", "") + "; " +
                                "read-date=" + DateTime.Now.ToString("R").Replace(",", ""));
            await context.Response.Body.WriteAsync(pdfBytes);
        }
    }

    public static class ShowPdfExtensions
    {
        public static IApplicationBuilder UseShowPdf(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<ShowPdf>();
        }
    }
}

In the Configure method of Startup.cs, you add (before app.UseStaticFiles();)

app.MapWhen(
    context => context.Request.Path.ToString().Contains("ShowPdf.mdwr", StringComparison.InvariantCultureIgnoreCase),
    appBranch => {
        appBranch.UseShowPdf();
    });

So, this URL will download a PDF file: /ShowPdf.mdwr?pdfid=idOfMyPdf

If embedding is required, this URL may be used in a PDF viewer.

Solution 2:[2]

Ok, I finally found the resolution for this. The ShowPDF.razor.cs code behind page is:

public partial class ShowPDF: ComponentBase
{
    private IReportData rdb;       // the database
    private ReportModel aReport;   // report model 

    /*
    aReport.ReportDocument holds the byte[]
    */
    string GetPDF(int ReportId)
    {
        this.rdb = new ReportData();
        aReport = rdb.GetWithReport(ReportId);
        return "data:application/pdf;base64," + Convert.ToBase64String(aReport.ReportDocument);
    }
}

and the ShowPDF.razor page is:

@page "/ShowPDF"
@page "/ShowPDF/{Report:int}"


@code {
    [Parameter]
    public int Report { get; set; }
}
<embed src="@GetPDF(Report)" visible="false" width="1500" height="2000" />

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 agua from mars