Read a PDF document in Blazor WebAssembly with iText7

Viewed 74

I am having a bit of a struggle reading a PDF using iText7 in Blazor WebAssembly.

The InputFile component creates a IBrowserFile:

<div>
    <InputFile OnChange="@OnFileSelection"></InputFile>
    <div class="row">
        <textarea>@outputText</textarea>
    </div>
</div>

I can then read the file with Stream - and iText7 will supposedly read that - but it won't give a page count or anything else that I have tried. It also doesn't seem to pass over the reader, and doesn't even seem to get to the pageCount.

    int pageCount = 0;
    IBrowserFile pdfFile = e.File;
    Stream stream = pdfFile.OpenReadStream();
    PdfDocument pdfDoc = new PdfDocument(new PdfReader(stream));
    pageCount = pdfDoc.GetNumberOfPages();
    stream.Close();
    outputText = $"{pageCount}";
    StateHasChanged();

I have also tried reading the Stream into a MemoryStream first, same outcome. I have followed the information here:

https://docs.microsoft.com/en-us/aspnet/core/blazor/file-uploads?view=aspnetcore-6.0&pivots=webassembly

Same outcome.

Is there a way to handle the PDF file in such a way as the functionality of iText7 remains intact, so you can get page counts, extracted text etc?

The file I am testing on is below the 500kb limit, it is 66kb. I don't need to display the PDF - I just need to know what the contents of it are ideally on a page by page basis, but for now, simply being able to read a page or get a page count would be a big step forward.

1 Answers

If you look at your developer console, you'll find that it's emitting the error:

Synchronous reads are not supported.

You'll notice you aren't using await anywhere, and, unfortunately, neither is iText7. Blazor strongly enforces use of asynchronous semantics and if it's violated, you'll see an error like this.

Fortunately, you can still make this work. You said:

I have also tried reading the Stream into a MemoryStream first, same outcome.

You should show what you tried, but my hunch is it looked something like this:

var copy = new MemoryStream();
stream.CopyTo(copy);
copy.Position = 0;
PdfDocument pdfDoc = new PdfDocument(new PdfReader(copy));

This will lead to the exact same error on the line .CopyTo. And for the same reasons. If you instead make the copy process properly use async semantics, it will work:

var copy = new MemoryStream();
await stream.CopyToAsync(copy);
copy.Position = 0;
PdfDocument pdfDoc = new PdfDocument(new PdfReader(copy));

Notice await stream.CopyToAsync(copy);. You'll need to make your surrounding method async in order for the await to work, but the return type ought to be a Task already. (And if it isn't, you can make it so)

Using this, I was able to see the page count display in your text area.

Related