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 Viewer uses adopted stylesheets, but removes third-party ones in the process.
This occurs since Telerik UI for Blazor version 7.0.0.
The workaround is to duplicate the third-party adoptedStylesheet as a regular CSS file.
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.
The PdfViewer GetFileAsync() method works in version 11.3.0, but only if the PDF Viewer loads a file by default. If the component renders blank and the user opens a file first, then the method still doesn't work and returns null.
Test page: https://blazorrepl.telerik.com/cpvuGQby16J4JlsE42
<p>Load a PDF file from your computer in both PDF Viewers and click the buttons.</p>
<strong>@TestResult</strong>
<br /><br />
<TelerikButton OnClick="@OnLoadButtonClick1" ThemeColor="@ThemeConstants.Button.ThemeColor.Primary">Get Current PDF 1</TelerikButton>
<TelerikPdfViewer @ref="@PdfViewerRef1"
Data="@PdfViewerData1"
AnnotationMode="@PdfViewerAnnotationMode.EnableForms"
Height="400px">
</TelerikPdfViewer>
<TelerikButton OnClick="@OnLoadButtonClick2" ThemeColor="@ThemeConstants.Button.ThemeColor.Primary">Get Current PDF 2</TelerikButton>
<TelerikPdfViewer @ref="@PdfViewerRef2"
Data="@PdfViewerData2"
AnnotationMode="@PdfViewerAnnotationMode.EnableForms"
Height="400px">
</TelerikPdfViewer>
@code {
#nullable enable
private TelerikPdfViewer? PdfViewerRef1 { get; set; }
private TelerikPdfViewer? PdfViewerRef2 { get; set; }
private byte[]? PdfViewerData1 { get; set; }
private byte[]? PdfViewerData2 { get; set; }
private string TestResult { get; set; } = string.Empty;
private async Task OnLoadButtonClick1()
{
var pdfSource = await PdfViewerRef1!.GetFileAsync();
TestResult = $"First PDF Viewer GetFileAsync() returned {pdfSource} at {DateTime.Now.ToString("HH:mm:ss")}";
}
private async Task OnLoadButtonClick2()
{
var pdfSource = await PdfViewerRef2!.GetFileAsync();
TestResult = $"Second PDF Viewer GetFileAsync() returned {(pdfSource != null ? pdfSource.ToString() : "null")} at {DateTime.Now.ToString("HH:mm:ss")}";
}
protected override void OnInitialized()
{
PdfViewerData1 = Convert.FromBase64String(PdfBase64);
}
private const string PdfBase64 = "JVBERi0xLjEKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDEvTWVkaWFCb3ggWy0zMCAtNjQgMjcwIDgwXSA+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9SZXNvdXJjZXM8PC9Gb250PDwvRjE8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9BcmlhbD4+ID4+ID4+L0NvbnRlbnRzIDQgMCBSPj5lbmRvYmoKNCAwIG9iajw8L0xlbmd0aCA1OT4+CnN0cmVhbQpCVAovRjEgMTggVGYKMCAwIFRkCihQREYgRmlsZSAuLi4pIFRqCkVUCmVuZHN0cmVhbQplbmRvYmoKeHJlZgowIDUKMDAwMDAwMDAwMCA2NTUzNSBmCjAwMDAwMDAwMjEgMDAwMDAgbgowMDAwMDAwMDg2IDAwMDAwIG4KMDAwMDAwMDE5NSAwMDAwMCBuCjAwMDAwMDA0OTAgMDAwMDAgbgp0cmFpbGVyIDw8ICAvUm9vdCAxIDAgUiAvU2l6ZSA1ID4+CnN0YXJ0eHJlZgo2MDkKJSVFT0Y=";
}
Rebinding the PDF Viewer multiple times leads to an ever increasing memory usage, which can ultimately cause a browser crash.
The issue started with Telerik UI for Blazor version 8.0.0 and does not occur in 7.1.0.
Test Page: https://blazorrepl.telerik.com/QTayOxvQ090qYPsb50
I want to detect when a user has added or removed an annotation in the PDF Viewer.
When a user invokes a Search tool, their intention is to directly write a text to search, therefore the edit for the search text should be focused immediately. In the current implementation, users have to manually focus the edit all the time, which is really inconvenient.
Related to PDF Viewer does not display editable Acro fields, which was fixed in version 8.0, but the problem with readonly Acro fields persisted.
This is a regression in version 7.0.0. Version 6.2.0 displays all the acro field values as expected.
Trying to upload a large file from a mobile device breaks the component.
Step to reproduce:
The issue can be reproduced only in version 8.0.0
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 together,
we are running into a problem with TelerikPdfViewer. When clicking the download button, download starts and performs properly.
BUT: the downloaded PDF file does not match the PDF that was provided via Data="@PdfData". On download something internally prepends some text to the PDF:
–€À³JS.ReceiveByteArray’Æ ‘¢%PDF-1.7 %úûüý 3 0 obj <</ca 1.00000 /AIS false >> endobj 5 0 obj
The original PDF file starts at "%PDF-1.7" (end of first line). That part before (including that "JS.ReceiveByteArray") was somehow added during the download workflow by Telerik. We ensured that the PDF data we provided to the viewer (via Data="@PdfData") ist valid. We did so by inspecting the byte[]-Array manually in the debugger as well as downloading it via a JS function to the client.
This is how we are using the TelerikPdfViewer. But the error occurs no matter if we are handling the OnDownload-Event (setting the filename) or not handlign that event at all (i.e. eliminating the OnDownload="@OnPdfDownload" completely)
<TelerikPdfViewer Data="@PdfData" Width="100%" Height="100%" Zoom="1m" OnDownload="@OnPdfDownload">
<PdfViewerToolBar>
<PdfViewerToolBarPagerTool />
<PdfViewerToolBarSpacer />
<PdfViewerToolBarZoomTool />
<PdfViewerToolBarSelectionTool />
<PdfViewerToolBarSearchTool />
<PdfViewerToolBarSpacer />
<PdfViewerToolBarDownloadTool />
<PdfViewerToolBarPrintTool />
</PdfViewerToolBar>
</TelerikPdfViewer>We use Telerik.UI.for.Blazor (6.2.0).
Thanks for your feedback on this issue and best regards!
Sebastian