The byte array returned by the GetFileAsync method is different when the file is opened through the PDFViewer's toolbar, and when the file is loaded initially using the Data parameter of the PDFViewer.
@using System.IO
@inject IJSRuntime JSRuntimeInstance
@inject HttpClient HttpClient
@inject NavigationManager NavigationManager
<PageTitle>Home</PageTitle>
<p>
<TelerikButton OnClick="@OnDownloadExportedFileClick">Get file with GetFileAsync and download</TelerikButton>
</p>
<strong>@TestResult</strong>
<br />
<br />
<TelerikPdfViewer @ref="@PdfViewerRef"
Data="@PdfViewerData"
AnnotationMode="@PdfViewerAnnotationMode.EnableForms"
Height="400px">
</TelerikPdfViewer>
@code {
#nullable enable
private TelerikPdfViewer? PdfViewerRef { get; set; }
private byte[]? PdfViewerData { get; set; }
private string TestResult { get; set; } = string.Empty;
public async Task OnDownloadExportedFileClick()
{
var result = await PdfViewerRef.GetFileAsync();
TestResult = $"First PDF Viewer GetFileAsync() returned {result} at {DateTime.Now.ToString("HH:mm:ss")}";
var base64String = Convert.ToBase64String(result);
var dataUrl = ToDataUrl("application/pdf", base64String);
_ = SaveFileAsDataUrlAsync("export.pdf", dataUrl);
}
private protected ValueTask SaveFileAsDataUrlAsync(string fileName, string dataUrl)
{
return InvokeVoidAsync("saveFile", fileName, dataUrl);
}
protected virtual ValueTask InvokeVoidAsync(string methodName, params object[] args)
{
try
{
return JSRuntimeInstance.InvokeVoidAsync($"TelerikBlazor.{methodName}", args);
}
catch (Exception)
{
return default;
}
}
private protected string ToDataUrl(string mimeType, string base64String)
{
return $"data:{mimeType};base64,{base64String}";
}
protected override async Task OnInitializedAsync()
{
PdfViewerData = System.IO.File.ReadAllBytes(@"pdf-viewer-form-filling-original.pdf");
await Task.Delay(1);
}
}
pdf-viewer-form-filling-original.pdf
The breakpoint in OnDownloadExportedFileClick is hit. Observe the difference in the byte array returned by the GetFileAsync method and saved in the "result" variable:
The byte array should be identical, regardless of the method of opening the file in the PDFViewer.
All
No response
The PDF standard allows two ways to configure Acro fields and relate them to inputs (widget annotations):
Adobe Acrobat supports both options. Telerik PdfProcessing supports only the first option, which is more commonly used. The PDF Viewer supports only the second option. If the PDF Viewer loads a file with the first configuration, the component saves new field values in such a way that they can't be retrieved by PdfProcessing. Moreover, if the PDF file is opened locally, it looks like the new values are there, but when you click on a field, the original value shows. The new value behaves like a placeholder rather than a real value.
Hallo,
i want to Render PDF Files with the PDF Viewer Component.
The Data of the PDF is already fetched from the API when the PDF-Viewer starts Rendering the Loading animation appears and freezes.
After a few Seconds the PDF will be Rendered.
The size of the PDF File is about 5MB.
=====
TELERIK EDIT: Here is a possible workaround - replace the built-in PDF Viewer LoaderContainer with another one with a different animation Type.
<div class="pdfviewer-wrapper">
<TelerikPdfViewer Height="600px" />
@* With a Loading... label *@
<TelerikLoaderContainer Class="pdf-loader-container"
OverlayThemeColor="@ThemeConstants.Loader.ThemeColor.Light"
Size="@ThemeConstants.Loader.Size.Large"
Visible="true" />
@* Without a Loading... label *@
@*<TelerikLoaderContainer Class="pdf-loader-container"
OverlayThemeColor="@ThemeConstants.Loader.ThemeColor.Light"
Visible="true">
<Template>
<TelerikLoader Size="@ThemeConstants.Loader.Size.Large"
Type="@LoaderType.Pulsing" />
</Template>
</TelerikLoaderContainer>*@
</div>
<style>
.pdfviewer-wrapper {
position: relative;
}
.pdf-loader-container,
.k-pdf-viewer .k-loader-container {
visibility: hidden;
}
.k-pdf-viewer:has(.k-loader-container:not([style*="none"])) + .pdf-loader-container {
visibility: visible;
}
</style>
@code {
private byte[]? PdfViewerData { get; set; }
}
I want to detect when a user has added or removed an annotation in the PDF Viewer.
Please expose a parameter to show or hide the "Select files..." button inside the empty PDF Viewer.
Currently, a possible workaround is to use CSS. Additionally, you may configure the Toolbar to not include the "Open" tool.
<style>
.no-open .k-blank-page {
display: none;
}
/* Use these selectors if you want to separately target the upload or the dropzone */
/* .no-open .k-external-dropzone,
.no-open .k-upload{
display: none;
} */
</style>
<TelerikPdfViewer Data="@PdfSource"
OnOpen="@OnPdfOpen"
Height="600px"
Class="no-open">
<PdfViewerToolBar>
<PdfViewerToolBarDownloadTool />
<PdfViewerToolBarPrintTool />
<PdfViewerToolBarSpacer />
<PdfViewerToolBarPagerTool />
<PdfViewerToolBarSpacer />
<PdfViewerToolBarZoomTool />
<PdfViewerToolBarSelectionTool />
<PdfViewerToolBarSearchTool />
<PdfViewerToolBarAnnotationsTool />
</PdfViewerToolBar>
</TelerikPdfViewer>
@code {
private byte[] PdfSource { get; set; }
private bool LoaderVisible { get; set; }
private async Task OnPdfOpen(PdfViewerOpenEventArgs args)
{
// Cancel the event for additional precaution in case someone bypasses the CSS and forces the page to show the button and the dropzone.
args.IsCancelled = true;
}
}
The PDF Viewer fails to display the loaded document if StateHasChanged() is called when the Data parameter is set.
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
PdfViewerData = await System.IO.File.ReadAllBytesAsync(......);
await Task.Delay(1);
StateHasChanged();
}
await base.OnAfterRenderAsync(firstRender);
}Test Page (run this in a server app):
<h1>PDF Viewer Tests</h1>
<h2>Load Initially</h2>
<TelerikPdfViewer Data="@FileData1"
EnableLoaderContainer="true"
Height="30vh"
Zoom="0.75m">
</TelerikPdfViewer>
<h2>Load On Demand</h2>
<TelerikButton ThemeColor="@ThemeConstants.Button.ThemeColor.Primary"
OnClick="@( async () => await LoadPdf(2) )">Load PDF</TelerikButton>
<TelerikPdfViewer Data="@FileData2"
EnableLoaderContainer="true"
Height="30vh"
Zoom="0.75m">
</TelerikPdfViewer>
@code {
private byte[]? FileData1 { get; set; }
private byte[]? FileData2 { get; set; }
protected async override Task OnInitializedAsync()
{
await LoadPdf(1);
}
public async Task LoadPdf(int id)
{
await Task.Delay(1000);
if (id == 2)
{
FileData2 = Convert.FromBase64String(PdfBase64);
}
else
{
FileData1 = Convert.FromBase64String(PdfBase64);
}
StateHasChanged();
await Task.Delay(300);
}
private const string PdfBase64 = "JVBERi0xLjEKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDEvTWVkaWFCb3ggWy00MCAtNjQgMjYwIDgwXSA+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9SZXNvdXJjZXM8PC9Gb250PDwvRjE8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9BcmlhbD4+ID4+ID4+L0NvbnRlbnRzIDQgMCBSPj5lbmRvYmoKNCAwIG9iajw8L0xlbmd0aCA1OT4+CnN0cmVhbQpCVAovRjEgMTggVGYKMCAwIFRkCihUZWxlcmlrIFBkZlZpZXdlciBmb3IgQmxhem9yKSBUagpFVAplbmRzdHJlYW0KZW5kb2JqCnhyZWYKMCA1CjAwMDAwMDAwMDAgNjU1MzUgZgowMDAwMDAwMDIxIDAwMDAwIG4KMDAwMDAwMDA4NiAwMDAwMCBuCjAwMDAwMDAxOTUgMDAwMDAgbgowMDAwMDAwNDkwIDAwMDAwIG4KdHJhaWxlciA8PCAgL1Jvb3QgMSAwIFIgL1NpemUgNSA+PgpzdGFydHhyZWYKNjA5CiUlRU9G";
}
Hello, I like the Telerik PDF Viewer for Blazor, but it's not supporting Table of Contents (TOC) links. I would like to request this feature so that there are links in the TOC automatically. I'm using Blazor WebAssembly.
Thank you for considering my request.
I want to have an option for digital signatures with browser-based certificate selection.
===
ADMIN EDIT
===
For the time being, you can use the following custom approach: Signing PDFs with PdfPRocessing in PdfViewer.
Adding the ability to fill in a PDF online in the PDF Viewer would open a lot of opportunity to the library.
The ability to fill-out, sign, and date would be great with a save callback, so it can be pushed to an API.