BitPdfViewer is a native pure-C# pdf viewer component for Blazor. It parses pdf files and renders pages as plain HTML/CSS DOM with no browser pdf plugin and no js library dependency, offering page navigation, zoom, rotation, search, thumbnails, bookmarks, download, print and fullscreen out of the box.

Notes

To use this component, you need to install the
Bit.BlazorUI.Extras
nuget package, as described in the Optional steps of the Getting started page.

Usage


Basic

<InputFile OnChange="OnBasicFileChange" accept=".pdf,application/pdf" />

<BitPdfViewer Source="basicSource" />
@code {
    private BitPdfSource basicSource = BitPdfSource.FromUrl("url-to-the-pdf-file.pdf", "file-name.pdf");
    
    // or from in-memory bytes:
    // private BitPdfSource basicSource = BitPdfSource.FromBytes(pdfBytes, "file-name.pdf");
    
    private async Task OnBasicFileChange(InputFileChangeEventArgs e)
    {
        if (e.FileCount == 0) return;
    
        const long maxSize = 512 * 1024 * 1024;
        if (e.File.Size <= 0 || e.File.Size > maxSize) return;
    
        using var stream = e.File.OpenReadStream(maxAllowedSize: maxSize);
        var bytes = new byte[(int)e.File.Size];
        await stream.ReadExactlyAsync(bytes);
    
        basicSource = BitPdfSource.FromBytes(bytes, e.File.Name);
    }
}
                    
The document can be provided from a URL (fetched via the registered HttpClient) or from in-memory bytes.

You can also select a pdf file from your computer to view it here:































































1
Sample PDF

Created for testing PDFObject

This PDF is three pages long. Three long pages. Or three short pages if
you’re optimistic. Is it the same as saying “three long minutes”, knowing
that all minutes are the same duration, and one cannot possibly be longer
than the other? If these pages are all the same size, can one possibly be
longer than the other?

I digress. Here’s some Latin. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec
odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum
imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris
massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per
conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero.

Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem
at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor.
Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia
aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh.

Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia
nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque
adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti.
Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices.

Suspendisse in justo eu magna luctus suscipit. Sed lectus. Integer euismod lacus luctus magna.
Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue
eget diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;
Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue
elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit
vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. Curabitur
sit amet mauris.

Morbi in dui quis est pulvinar ullamcorper. Nulla facilisi. Integer lacinia sollicitudin massa. Cras
metus. Sed aliquet risus a tortor. Integer id quam. Morbi mi. Quisque nisl felis, venenatis tristique,
dignissim in, ultrices sit amet, augue. Proin sodales libero eget ante. Nulla quam. Aenean laoreet.
Vestibulum nisi lectus, commodo ac, facilisis ac, ultricies eu, pede. Ut orci risus, accumsan
porttitor, cursus quis, aliquet eget, justo. Sed pretium blandit orci.

Ut eu diam at pede suscipit sodales. Aenean lectus elit, fermentum non, convallis id, sagittis at,
neque. Nullam mauris orci, aliquet et, iaculis et, viverra vitae, ligula. Nulla ut felis in purus
aliquam imperdiet. Maecenas aliquet mollis lectus. Vivamus consectetuer risus et tortor. Lorem

Toolbar & Height

<BitButton IsEnabled="plainSource is null"
           OnClick='() => plainSource = BitPdfSource.FromUrl("url-to-the-pdf-file.pdf", "file-name.pdf")'>Load document</BitButton>

<BitPdfViewer Source="plainSource" ShowToolbar="false" Height="600px" />
@code {
    private BitPdfSource? plainSource;
}
                    
The toolbar can be hidden and the height of the viewer customized.



No document loaded.

Canvas render mode

<BitButton IsEnabled="canvasSource is null"
           OnClick='() => canvasSource = BitPdfSource.FromUrl("url-to-the-pdf-file.pdf", "file-name.pdf")'>Load document</BitButton>

<InputFile OnChange="OnCanvasFileChange" accept=".pdf,application/pdf" />

<BitPdfViewer Source="canvasSource" RenderMode="BitPdfRenderMode.Canvas" />
@code {
    private BitPdfSource? canvasSource;
    
    private async Task OnCanvasFileChange(InputFileChangeEventArgs e)
    {
        if (e.FileCount == 0) return;
    
        const long maxSize = 512 * 1024 * 1024;
        if (e.File.Size <= 0 || e.File.Size > maxSize) return;
    
        using var stream = e.File.OpenReadStream(maxAllowedSize: maxSize);
        var bytes = new byte[(int)e.File.Size];
        await stream.ReadExactlyAsync(bytes);
    
        canvasSource = BitPdfSource.FromBytes(bytes, e.File.Name);
    }
}
                    
In
Canvas
mode, the page content is painted onto a per-page canvas by replaying a display list produced by the C# engine (far fewer DOM nodes on graphics-heavy documents), while selection, search and links still work through the DOM text layer.



You can also select a pdf file from your computer to view it here:


No document loaded.

Events

<BitButton IsEnabled="eventsSource is null"
           OnClick='() => eventsSource = BitPdfSource.FromUrl("url-to-the-pdf-file.pdf", "file-name.pdf")'>Load document</BitButton>

<BitPdfViewer Source="eventsSource"
              OnDocumentLoaded='() => eventsLog.Add("Document loaded")'
              OnPageChanged='p => eventsLog.Add($"Page changed: {p}")'
              OnError='e => eventsLog.Add($"Error: {e}")' />

<div>Events:</div>
<div style="max-height:8rem;overflow:auto">
    @foreach (var log in Enumerable.Reverse(eventsLog).Take(5))
    {
        <div>@log</div>
    }
</div>
@code {
    private BitPdfSource? eventsSource;
    
    private readonly List<string> eventsLog = [];
}
                    
The viewer reports document loading, page changes, warnings and errors.



No document loaded.

Events:

Public API

<BitButton IsEnabled="publicApiSource is null"
           OnClick='() => publicApiSource = BitPdfSource.FromUrl("url-to-the-pdf-file.pdf", "file-name.pdf")'>Load document</BitButton>

<div style="display:flex;gap:0.5rem;flex-wrap:wrap;align-items:center">
    <BitButton OnClick="() => pdfViewerRef.GoToPage(1)">First</BitButton>
    <BitButton OnClick="() => pdfViewerRef.PrevPage()">Prev</BitButton>
    <BitTag Variant="BitVariant.Outline" Text="@($"{pdfViewerRef?.CurrentPage}/{pdfViewerRef?.PageCount}")" Color="BitColor.Info" />
    <BitButton OnClick="() => pdfViewerRef.NextPage()">Next</BitButton>
    <BitButton OnClick="() => pdfViewerRef.GoToPage(pdfViewerRef.PageCount)">Last</BitButton>
    <BitButton OnClick="() => pdfViewerRef.ZoomOut()">Zoom -</BitButton>
    <BitButton OnClick="() => pdfViewerRef.ZoomIn()">Zoom +</BitButton>
    <BitButton OnClick="() => pdfViewerRef.RotateClockwise()">Rotate</BitButton>
    <BitButton OnClick="() => pdfViewerRef.Print()">Print</BitButton>
</div>

@* BackgroundRendering offloads parse/render to a worker thread when the runtime
   has one (Blazor Server, or a WASM app built with WasmEnableThreads). *@
<BitPdfViewer @ref="pdfViewerRef" BackgroundRendering
              Source="publicApiSource"
              ShowToolbar="false"
              OnDocumentLoaded="StateHasChanged"
              OnPageChanged="_ => StateHasChanged()" />
@code {
    private BitPdfSource? publicApiSource;
    
    private BitPdfViewer pdfViewerRef = default!;
}
                    
The viewer can be driven from outside using its public members (e.g. with a hidden toolbar).



/

No document loaded.

API

BitPdfViewer parameters

Name Type Default value Description
Source BitPdfSource? null The document to display.
Height string? null The CSS height of the viewer container. When not set, the viewer height is responsive: capped at 780px and shrinking to fit the viewport on small screens.
ShowToolbar bool true Whether the toolbar is shown.
InitialZoomMode BitPdfZoomMode BitPdfZoomMode.FitWidth The initial zoom behavior.
TextCoalescing BitPdfTextCoalescing BitPdfTextCoalescing.Exact How painted text is emitted. Compact merges same-line, same-style runs into one span per visual line (far fewer DOM nodes on per-glyph pdfs).
RenderMode BitPdfRenderMode BitPdfRenderMode.Html How page content is painted. Canvas replays a display list onto a per-page canvas, while Html (the default) renders prerenderable positioned DOM.
BackgroundRendering bool false Offloads document parsing and page rendering to a background thread so scrolling and navigation stay responsive while a complex page renders. Only has an effect when the runtime provides a spare thread (Blazor Server, or a Blazor WebAssembly app built with WasmEnableThreads); on the default single-threaded WebAssembly runtime it is a safe no-op.
OnDocumentLoaded EventCallback The callback for when a document has finished loading.
OnPageChanged EventCallback<int> The callback for when the focused page changes (with the 1-based page number).
OnError EventCallback<string> The callback for when loading or rendering fails, with the error message.
OnWarnings EventCallback<IReadOnlyList<string>> The callback raised after a document loads with any non-fatal diagnostics (e.g. a damaged file whose cross-reference table had to be rebuilt).
OnPasswordRequested Func<Task<string?>>? null Invoked when an encrypted document needs a password. Return the password to retry, or null/empty to cancel. If unset, a password error surfaces through OnError instead.

BitPdfViewer public members

Name Type Default value Description
PageCount int The number of pages of the current document.
CurrentPage int The currently focused page (1-based).
Zoom double The current zoom factor (1 means 100%).
HasOutline bool Whether the document exposes any bookmarks.
GoToPage Task GoToPage(int pageNumber) Navigates to the provided page number (1-based).
NextPage Task NextPage() Navigates to the next page.
PrevPage Task PrevPage() Navigates to the previous page.
ZoomIn Task ZoomIn() Zooms in by 20%.
ZoomOut Task ZoomOut() Zooms out by 20%.
SetZoomMode Task SetZoomMode(BitPdfZoomMode mode) Sets the zoom mode (fit-width, fit-page, actual size or custom).
RotateClockwise Task RotateClockwise() Rotates all pages 90 degrees clockwise.
Download Task Download() Downloads the original document bytes.
Print Task Print() Opens the browser print dialog with all pages of the document.
ToggleFullscreen Task ToggleFullscreen() Toggles the fullscreen mode of the viewer.
RenderPageHtml string RenderPageHtml(int pageNumber) Renders a single page (1-based) to self-contained HTML, or an empty string when no document is loaded or the number is out of range.
ExtractPageText string ExtractPageText(int pageNumber) Extracts the visible text of a single page (1-based) for search or copy, or an empty string when unavailable.

BitComponentBase parameters

Name Type Default value Description
AriaLabel string? null Gets or sets the accessible label for the component, used by assistive technologies.
Class string? null Gets or sets the CSS class name(s) to apply to the rendered element.
Dir BitDir? null Gets or sets the text directionality for the component's content.
ForceAnimation bool false Gets or sets a value indicating whether the component's animations play at their full duration even when reduced motion is requested.
HtmlAttributes Dictionary<string, object> new Dictionary<string, object>() Captures additional HTML attributes to be applied to the rendered element, in addition to the component's parameters.
Id string? null Gets or sets the unique identifier for the component's root element.
IsEnabled bool true Gets or sets a value indicating whether the component is enabled and can respond to user interaction.
Style string? null Gets or sets the CSS style string to apply to the rendered element.
TabIndex string? null Gets or sets the tab order index for the component when navigating with the keyboard.
Visibility BitVisibility BitVisibility.Visible Gets or sets the visibility state (visible, hidden, or collapsed) of the component.

BitComponentBase public members

Name Type Default value Description
UniqueId Guid Guid.NewGuid() Gets the readonly unique identifier for the component's root element, assigned when the component instance is constructed.
RootElement ElementReference Gets the reference to the root HTML element associated with this component.

BitPdfSource properties

Identifies where a pdf document is loaded from. A source is either a byte buffer already in memory (BitPdfSource.FromBytes), or a URL the document can be fetched from (BitPdfSource.FromUrl).

Name Type Default value Description
Bytes byte[]? null Raw document bytes, when the source is an in-memory buffer.
Url string? null The URL to fetch the document from, when the source is remote.
FileName string? null An optional display name (e.g. the original file name).
Password string? null The password to open an encrypted document, if known up front (also see the WithPassword method).

BitPdfZoomMode enum

Name Value Description
Custom 0 An explicit zoom factor is applied (the user picked a percentage).
FitWidth 1 Each page is scaled so its width fills the viewport.
FitPage 2 Each page is scaled so the whole page fits in the viewport.
ActualSize 3 Pages are shown at their natural size (one CSS pixel per point).

BitPdfRenderMode enum

Name Value Description
Html 0 Pages render to positioned HTML/CSS DOM (the default). Fully prerenderable and crisp at any zoom.
Canvas 1 Page content is painted onto a per-page canvas by replaying a display list produced by the C# engine. Far fewer DOM nodes; selection, search and links still work through the DOM text layer, and zoom changes re-rasterize the canvases so text stays crisp. Requires JavaScript, so no prerender.

BitPdfTextCoalescing enum

Name Value Description
Exact 0 Every show-text run keeps its own positioned span, so each glyph run lands at its exact pdf-computed position. Highest fidelity, but per-glyph pdfs emit one span per character.
Compact 1 Adjacent runs on the same baseline with identical style are merged into one span per visual line. Dramatically fewer DOM nodes on per-glyph pdfs, at the cost of small intra-line position drift. Rotated text is never coalesced and stays exact.

BitVisibility enum

Name Value Description
Visible 0 The content of the component is visible.
Hidden 1 The content of the component is hidden, but the space it takes on the page remains (visibility:hidden).
Collapsed 2 The component is hidden (display:none).

BitDir enum

Name Value Description
Ltr 0 Ltr (left to right) is to be used for languages that are written from the left to the right (like English).
Rtl 1 Rtl (right to left) is to be used for languages that are written from the right to the left (like Arabic).
Auto 2 Auto lets the user agent decide. It uses a basic algorithm as it parses the characters inside the element until it finds a character with a strong directionality, then applies that directionality to the whole element.

Feedback

You can give us your feedback through our GitHub repo by filing a new Issue or starting a new Discussion.


Or you can review / edit this page on GitHub.


Or you can review / edit this component on GitHub.