We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Loading PDF from NodeJS backend

Hello, 

I can not wrap my head around the loading of a PDF file from a Url provide by a nodejs backend.

Part of my backend code that provides the PDF file is the following:

else if (request.method === 'GET' && request.url === '/docs') {

let pdfManual = path.join(__dirname, "manuals/EV3.pdf");
let stat = fs.statSync((pdfManual));

response.writeHead(200, {
'Content-Type': 'application/pdf',
'Content-Length': stat.size
});

let readStream = fs.createReadStream(pdfManual);
readStream.pipe(response);

} else {

When i load the url in my chrome browser it loads the pdf nicely,

My frontend is angular 4.  Below is my basic html template which loads te pdfViewer.

<ej-pdfviewer [(serviceUrl)]="service" id="pdfviewer" style="width:100%;min-height:100%">
</ej-pdfviewer>
My component code is also very basic.

import {Component, Input, OnInit} from '@angular/core';

@Component({
selector: 'hmi-pdf-viewer',
templateUrl: './pdf-viewer.component.html',
styleUrls: ['./pdf-viewer.component.css']
})
export class PdfViewerComponent implements OnInit {

service: string;

constructor() {
this.service = 'http://localhost:3000/docs';
}

ngOnInit(): void {

}
}
Now the problem I can't get my head around is the serviceUrl part. In most of the samples provided the PDF file is loaded from the Syncfusion site. Which host a service/controller that provides the pdf. But i cannot find an example how I could implement this in my own backend. I thought it would be as simple as requesting a PDF file from my server backend.

When I load the pdf nothing is displayed. So what is the proper way of realising this.

I use angular 4.3.3 and syncfusion-javascript/ej-angular2 15.3.26

Thanks for help,
Kevin


9 Replies

SA Sabari Anand Senthamarai Kannan Syncfusion Team August 11, 2017 07:29 AM UTC

Hi Kevin, 
 
Thank you for using Syncfusion products. 
 
After analyzing your query, we came to know that you are trying to load the PDF document using the nodejs backend. We do not support loading the PDF document using the nodejs backend. We support to load the PDF document to the PDF viewer control using web API controller which is also used for downloading and further processing the  PDF document. So in Angular 4 application, we need to refer the URL of the web API controller(service) as the value of serviceUrl property of the PDF viewer control. The code snippet for assigning the serviceUrl property of the PDF viewer control is as follows. 
 
Code Snippet: 
 
HTML Template: 
<ej-pdfviewer [(serviceUrl)]="service" id="pdfviewer" style="width:100%;min-height:100%"> 
</ej-pdfviewer> 
 
Component code: 
export class PdfViewerComponent { 
  service: string; 
  constructor() { 
    this.service = http://localhost:57968/api/PdfViewer'; 
  } 
} 
 
We have provided the web API service application for your reference below. 
 
 
Please let us know if you need any further assistance. 
 
Regards, 
Sabari Anand 



KS Kevin Smit August 11, 2017 10:25 AM UTC

Hi Sabari,

Thanks for your answer. So that's not the way to go for me.

I read in the docs that the javascript PDFViewer supports loading, form disk, Stream and Byte Array. What about the local from disk option or Byte Array?

I suppose i can use the PDFViewers load function to load an local PDF. I have tried this in my angular template but it complains it cannot find the load function.

for example: 

html template: 

<ej-pdfviewer [(serviceUrl)]="service" id="pdfviewer" style="width:100%;min-height:100%">
</ej-pdfviewer>

And in the TypeScript File:

ngAfterViewInit() {

     let elem = document.getElementById("pdfviewer");

     elem.load('localfile.pdf');  // file or url ?

}

The apidocs: pdfviewer load get the container where the pdfviewer is created. But i cannot get this to work in Angular 4 where I use the element selector <ej-pdfviewer > ...

Also tried to get the element with <ej-pdfviewer #pdfElem  ...... 

and the tried to get the element in Typescript:

pdfElem.load('localfile.pdf') 

But this does not work either.

Could point me in the right direction to load an PDF this way, this would also solve my problem to handle PDF documents voor now, even better a way to handle the docs as byte Array or Stream, this way i can first download them to my client or create an stream from my backend.

Thanks for the help.

Kevin



SA Sabari Anand Senthamarai Kannan Syncfusion Team August 14, 2017 10:40 AM UTC

Hi Kevin, 
  
Thank you for your update. 
  
Please find the details for your queries in the below table. 
  
Query 
Details 
I read in the docs that the javascript PDFViewer supports loading, form disk, Stream and Byte Array. What about the local from disk option or Byte Array? 
We can load the PDF document as a path from the local disk, stream or byte array on the server side (Web API controller) while loading the PDF viewer control initially. On the client side, we support to load PDF documents as string (file path of the PDF document) and base64 string (PDF document data as base 64 string) into the PDF viewer control. 
I suppose i can use the PDFViewers load function to load an local PDF. I have tried this in my angular template but it complains it cannot find the load function. 
  
The apidocs: pdfviewer load get the container where the pdfviewer is created. But i cannot get this to work in Angular 4 where I use the element selector <ej-pdfviewer > ... 
Also tried to get the element with <ej-pdfviewer #pdfElem  ......  
and the tried to get the element in Typescript: 
pdfElem.load('localfile.pdf')  
But this does not work either. 
Could point me in the right direction to load an PDF this way, this would also solve my problem to handle PDF documents voor now, even better a way to handle the docs as byte Array or Stream, this way i can first download them to my client or create an stream from my backend. 
We have created a sample to load the PDF document from the client side using the load() function. You can download the sample from the following link. 
  
Sample link: 
Web Service link: 
  
In the above sample, the PDF document provided as a path in the server will be loaded in the PDF viewer control. We have provided a button “Load” to load a document from the Data folder of the web service project. 
  
Note: Please modify the path provided in the web API controller in order to load the PDF document from different locations. 
  
Please let us know that the above sample meets your requirements. If not, please provide us further details about your requirements. It will be helpful for us to analyze further and assist you better. 
  
Please let us know if you need any further assistance. 
  
Regards, 
Sabari Anand 



KS Kevin Smit August 15, 2017 01:51 PM UTC

Hello Sabari,

Thanks for the clarification.

Te webservice project helped me figure out the post link to request the PDF. I rewrote it to nodejs/Express backend:

/ ---------------------------------------------------------------------------------------------------------------------
// CREATE EXPRESS SERVER AND INITIALIZE SOCKET IO
// ---------------------------------------------------------------------------------------------------------------------
app.get('/', (req, res) => {
res.send(`Hello client 2`);
});

app.options('/manuals/Load', cors());
app.post('/manuals/Load', cors(), (req, res) => {

console.log(req);

let pdfManual = path.join(__dirname, "manuals/DS4.pdf");
// let pdf = pdfManual.toString('base64');

let readStream = fs.createReadStream(pdfManual);
readStream.pipe(new Base64Encode()).pipe(res);

});

The cors function takes care of the headers defined in the web.config file:

<customHeaders>

<add name="Access-Control-Allow-Headers" value="accept, maxdataserviceversion, origin, x-requested-with, dataserviceversion,content-type" />

<add name="Access-Control-Allow-Origin" value="*" />

<add name="Access-Control-Max-Age" value="1728000" />

</customHeaders>

With Base64Encode I encode the pdf to a base64 string as stated in your answer:

We can load the PDF document as a path from the local disk, stream or byte array on the server side (Web API controller) while loading the PDF viewer control initially. On the client side, we support to load PDF documents as string (file path of the PDF document) and base64 string (PDF document data as base 64 string) into the PDF viewer control. 

Now when the pdf viewer initilizes in my angular project:


<ej-pdfviewer [(serviceUrl)]="service" id="pdfviewer" style="width:100%;min-height:100%">
</ej-pdfviewer>

It gets the pdf as an base64 encoded string:


But it's not loading in the PDFViewer control. Can you help me get the last peace of the puzzle complete? 

I don't know which extra info/code i need to provide. The main peaces are in the code above and in my first post.

Thanks for support



SA Sabari Anand Senthamarai Kannan Syncfusion Team August 18, 2017 10:39 AM UTC

Hi Kevin, 
  
Thank you for your update. 
  
We can load the PDF document data as base64 string by using the load() API of the PDF viewer control in client side. The code snippet for loading the PDF document data as base64 string in the client side is as follows. 
  
Code snippet
              var pdfviewerObject = $("#pdfviewer1").ejPdfViewer("instance"); 
              pdfviewerObject.load(base64string); 
  
We have created a sample to demonstrate the same. You can download the sample from the following link. 
  
  
In the above sample, we have used a Upload box control to convert the file selected into base64 string. The base64 string then can be loaded in the PDF viewer control using the load() API in client side.  
  
Please let us know that the above sample meets your requirements. If not, please let us know further details about your requirements. It will be helpful for us to analyze further and assist you better. 
  
Regards, 
Sabari Anand 



KS Kevin Smit August 19, 2017 12:23 PM UTC

Hi Sabari,

I cannot get it to work. I implemented the sample code and reading in the PDF works fine.

loadPDF(pdfFileName: string): void {

this.httpservice.getPDFFile(pdfFileName)
.subscribe(
(response) => {

// console.log(response.blob());

let reader = new FileReader();
reader.readAsDataURL(response.blob());
reader.onload = () => {
let pdfViewerObject = $("#pdfviewer").ejPdfViewer("instance");
let pdfFile = reader.result;
console.log(pdfFile);
pdfViewerObject.load(pdfFile);
}
},
(error) => console.log(error)
);

I made an call to the backend server (pdfviewer is requesting a path with Load) and im sending back the PDF as blob. 

If i then console log it (console.log(pdfFile)) it nicely prints out the PDF.

Now the magic happens:

When i load the pdf in the PDFViewer its makes an request to the server again and sends the pdf as an Base64 encoded string to the path ***/FileUpload.

My questions are:

1) Why is the control sending back the base encoded string to the server an not loading it directly if it supports base64 encode strings

2 ) After viewing back the controllers example. The FileUpload function process the pdf on the server:

public object FileUpload(Dictionary<string, string> jsonResult)
{
PdfViewerHelper helper = new PdfViewerHelper();

if (jsonResult.ContainsKey("uploadedFile"))
{
var fileurl = jsonResult["uploadedFile"];
byte[] byteArray = Convert.FromBase64String(fileurl);
MemoryStream stream = new MemoryStream(byteArray);
helper.Load(stream);
}
string output = JsonConvert.SerializeObject(helper.ProcessPdf(jsonResult));
return output;
}

why is this nessesary if it already knows the base64 encode pdf from the FileReader();

3) Does the controller does something special with the PDF or structure of the response (eg. application type, application size) in the backend or is the control using native PDF.

 if so i do not understand why it is not loading the the encoded pdf string natively.

Could you maybe provide some structure the controller sends back with the Load and/or FileUpload functions. If thats clear in can improve my NodeJS backend (I'm not using a .NET backend) to send the correct peaces to the control. Or maybe the control can directly load the base64 encode PDF without sending it for processing to the backend again?



SA Sabari Anand Senthamarai Kannan Syncfusion Team August 21, 2017 06:58 AM UTC

Hi Kevin, 
  
Thank you for your update. 
  
Please find the details for your queries in the following table. 
  
Queries 
Details 
Why is the control sending back the base encoded string to the server and not loading it directly if it supports base64 encode strings 
The PDF document data as base64 string is sent to the web API controller(server) to parse and decode the PDF elements in server side, then returns the PDF data as JSON string to the client side and rendered the PDF document element in the PDF viewer control.  
why is this nessesary if it already knows the base64 encode pdf from the FileReader(); 
  
Does the controller does something special with the PDF or structure of the response (eg. application type, application size) in the backend or is the control using native PDF. 
if so i do not understand why it is not loading the the encoded pdf string natively. 
  
Or maybe the control can directly load the base64 encode PDF without sending it for processing to the backend again? 
We do not support rendering the PDF document natively on the client side of the PDF viewer control. The web API controller is necessary for the rendering of the PDF document in the PDF viewer control. The client side of the PDF viewer control does not handle the decoding PDF elements (images and texts) and its structure. These operations are done in the web API controller and returns the PDF data as JSON string to the client. On the client side, the UI elements in the PDF document and the document content will be rendered in the PDF viewer control. 
Could you maybe provide some structure the controller sends back with the Load and/or FileUpload functions. If thats clear in can improve my NodeJS backend (I'm not using a .NET backend) to send the correct peaces to the control. 
Please find the usage of the action methods in the web API controller for the PDF viewer control below. 
Load – Used for loading the PDF document initially and used for further processing of the document. 
FileUpload – Used for loading the PDF document as base64String using the load() API. 
Download – Used for downloading the PDF document from the PDF viewer control. 
  
Kindly refer the below UG documentation link to know more about the PDF viewer WebAPI controller.  
  
Please refer the web API service sample provided earlier for further details. 
  
Please let us know if you need any further assistance. 
  
Regards, 
Sabari Anand 



KS Kevin Smit September 9, 2017 09:39 AM UTC

Hi,


I did some experimenting but cannot implement the backend with nodejs. I have to take this another route.

Thanks for support and explaining the principle.



SA Sabari Anand Senthamarai Kannan Syncfusion Team September 11, 2017 11:01 AM UTC

Hi Kevin, 
  
Thank you for your update. 
  
Please let us know if you need any further technical assistance. We are happy to assist you in the same. 
  
Regards, 
Sabari Anand 


Loader.
Up arrow icon