How to Load and Save PDF Files from a Server Using a Standalone React PDF Viewer?
Description:
This article explains how to load and save PDF files from a server using the Syncfusion® PDF Viewer component in a standalone React application. This setup enables seamless document handling by integrating client-side viewer actions with server-side APIs.
Solution:
To load and save PDF files from a server, we use custom HTTP endpoints that interact with the Syncfusion PDF Viewer. The client sends requests to load a PDF file as a base64 string and saves annotations or changes back to the server using saveAsBlob()
.
Prerequisites:
- Syncfusion PDF Viewer Setup: Make sure the Syncfusion® PDF Viewer is installed and set up in your React project. Follow the Getting Started with Syncfusion® PDF Viewer for React guide if you haven’t already.
- Basic Knowledge of React: Familiarity with React components and the basic setup of React projects will help you follow along with the implementation.
- Server Actions: A server-side controller (ASP.NET Core) must be set up to handle Load and Download endpoints.
Code Snippet
Client: index.js
import { createRoot } from 'react-dom/client';
import './index.css';
import * as React from 'react';
import { PdfViewerComponent, Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print, TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer, Inject } from '@syncfusion/ej2-react-pdfviewer';
function Default() {
let viewer;
function load() {
var xhr = new XMLHttpRequest();
var fileName = 'annotations.pdf';
var url = `https://localhost:7255/pdfviewer/Load`;
var data = {
document: fileName,
isFileName: true
};
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.responseType = 'arraybuffer';
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var blob = new Blob([xhr.response], { type: 'application/pdf' });
var reader = new FileReader();
reader.onload = function () {
var base64String = reader.result;
viewer.load(base64String);
};
reader.readAsDataURL(blob);
}
};
xhr.send(JSON.stringify(data));
}
function Save() {
const url = "https://localhost:7255/pdfviewer/Download";
viewer.saveAsBlob().then((blob) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function (e) {
const base64String = e.target?.result.toString();
const xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-type', 'application/json; charset=UTF-8');
const requestData = JSON.stringify({ base64String });
xhr.onload = function () {
if (xhr.status === 200) {
console.log('Download successful:', xhr.responseText);
} else {
console.error('Download failed:', xhr.statusText);
}
};
xhr.onerror = function () {
console.error('An error occurred during the download:', xhr.statusText);
};
xhr.send(requestData);
};
});
};
return (<div>
<div className='control-section'>
<PdfViewerComponent ref={(scope) => { viewer = scope; }} id="container" documentPath="https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf" resourceUrl="https://cdn.syncfusion.com/ej2/23.2.6/dist/ej2-pdfviewer-lib" style={{ 'height': '640px' }}>
<button onClick={load}>load</button>
<button onClick={Save}>Save</button>
<Inject services={[Toolbar, Magnification, Navigation, LinkAnnotation, BookmarkView, ThumbnailView, Print, TextSelection, TextSearch, Annotation, FormFields, FormDesigner, PageOrganizer]}/>
</PdfViewerComponent>
</div>
</div>);
}
export default Default;
const root = createRoot(document.getElementById('sample'));
root.render(<Default />);
Server: PdfViewerController.cs
public PdfViewerController(IWebHostEnvironment hostingEnvironment, IMemoryCache cache)
{
_hostingEnvironment = hostingEnvironment;
_cache = cache;
Console.WriteLine("PdfViewerController initialized");
}
[HttpPost("Load")]
[Microsoft.AspNetCore.Cors.EnableCors("MyPolicy")]
[Route("[controller]/Load")]
public IActionResult Load([FromBody] Dictionary<string, string> jsonObject)
{
Console.WriteLine("Load called");
MemoryStream stream = new MemoryStream();
if (jsonObject != null && jsonObject.ContainsKey("document"))
{
if (bool.Parse(jsonObject["isFileName"]))
{
string documentPath = GetDocumentPath(jsonObject["document"]);
if (!string.IsNullOrEmpty(documentPath))
{
byte[] bytes = System.IO.File.ReadAllBytes(documentPath);
stream = new MemoryStream(bytes);
}
else
{
string fileName = jsonObject["document"].Split(new string[] { "://" }, StringSplitOptions.None)[0];
if (fileName == "http" || fileName == "https")
{
WebClient webClient = new WebClient();
byte[] fileBytes = webClient.DownloadData(jsonObject["document"]);
stream = new MemoryStream(fileBytes);
}
else
{
return this.Content(jsonObject["document"] + " is not found");
}
}
}
else
{
byte[] bytes = Convert.FromBase64String(jsonObject["document"]);
stream = new MemoryStream(bytes);
}
}
byte[] pdfData = stream.ToArray();
return File(pdfData, "application/pdf");
}
[HttpPost("Download")]
[Microsoft.AspNetCore.Cors.EnableCors("MyPolicy")]
[Route("[controller]/Download")]
public IActionResult Download([FromBody] Dictionary<string, string> jsonObject)
{
string base64 = jsonObject["base64String"];
string base64String = base64.Split(new string[] { "data:application/pdf;base64," }, StringSplitOptions.None)[1];
byte[] byteArray = Convert.FromBase64String(base64String);
string folderPath = Path.Combine(_hostingEnvironment.ContentRootPath, "Data");
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
string fileName = "test.pdf";
string filePath = Path.Combine(folderPath, fileName);
// Save the file to the correct path
System.IO.File.WriteAllBytes(filePath, byteArray);
return Ok();
}
//Gets the path of the PDF document
private string GetDocumentPath(string document)
{
string documentPath = string.Empty;
if (!System.IO.File.Exists(document))
{
var path = _hostingEnvironment.ContentRootPath;
if (System.IO.File.Exists(path + "/Data/" + document))
documentPath = path + "/Data/" + document;
}
else
{
documentPath = document;
}
Console.WriteLine(documentPath);
return documentPath;
}
Steps to Use the Code:
- Add the provided client and server code to your React and ASP.NET Core applications respectively.
- Start the ASP.NET Core backend server to host the Load and Download endpoints.
- Run the React frontend application using
npm start
to launch the PDF Viewer interface. - Click the
Load
button to fetch and display the PDF file from the server. - Make annotations or edits using the Syncfusion PDF Viewer.
- Click the
Save
button to send the updated PDF back to the server. - Open the saved PDF from the server’s Data folder using PDF viewer to verify the changes.
Key Features Used in the Code:
- Custom Load Endpoint: Loads PDF from server using XMLHttpRequest and converts it to base64 for viewer rendering.
- Save as Blob: Uses saveAsBlob() to capture the current PDF state and sends it to the server for saving.
- Server-Side File Handling: ASP.NET Core controller handles file reading, conversion, and saving using base64 encoding.
Sample Link:
You can find the full sample in our GitHub repository.
Conclusion:
I hope this article helped you understand how to load and save PDF files from a server using the Syncfusion® React PDF Viewer. This approach enables efficient document management and annotation workflows in standalone applications.
You can refer to ASP.NET Core PDF Viewer Feature Tour page to know about its other groundbreaking feature representations and documentation, and how to quickly get started for configuration specifications.
You can also explore our ASP.NET Core PDF Viewer Example to understand how to create and manipulate data.
For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion, you can try our 30-day free trial to check out our other controls.
If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forums, Direct-Trac, or feedback portal. We are always happy to assist you!