user

Mohamed Atef

14 Feb 2022

Display PDF in Reactjs from Authenticated API

React js

showing PDF in React js is easy but if you are dealing with API authenticated or not it can be more difficult because you will need more effort to get it done, In my article, I am going to explain everything and make it easy on you, by providing explanation & ready codes which hopefully work with you 

The first step install Axios

Axios is a very important package in NPM helps you use HTTP requests easily and in professional way, you can install it in your React Project using this command 

npm i axios

or 

bower install axios

and then in Our React js application, we gonna create a new component and we can add our initial elements in it 

import React from 'react';
import { Box, withStyles, Typography } from '@material-ui/core';
import Page from 'src/components/Page';
import axios from 'axios';

const styles = ({
 root: {
 padding: '90px'
 }
});

class HomeView extends React.Component {
 
 render(){

 const { classes } = this.props;

 return (
 <Page title="Homepage">
 <Box p={10} className={classes.root}>
 <Typography variant='h1' color="textPrimary">
 Hello world
 </Typography>
 </Box>
 </Page>
 );
 }
}
export default withStyles(styles)(HomeView);

then we can start Writing the foundations of the function which will get the PDF from the API and store it in our browser, I will use componentDidMount because I want to apply the function once the component show up

 async getPDF(){
 try{

 }catch(err){
 console.error(err);
 }
 }

 componentWillUnmount(){
 this.getPDF();
 } 

and I will create a state to save the Blob URL which we will create then I added a loading component

import React from 'react';
import { Box, withStyles, Typography } from '@material-ui/core';
import Page from 'src/components/Page';
import axios from 'axios';
import Loading from 'src/components/Loading';

const styles = ({
 root: {
 padding: '90px'
 }
});

class HomeView extends React.Component {

 state = {
 blobURL: null
 };

 async getPDF(){
 try{

 }catch(err){
 console.error(err);
 }
 }

 componentDidMount(){
 this.getPDF();
 }
 
 render(){

 const { classes } = this.props;

 if(!this.state.blobURL){
 return <Loading />
 }

 return (
 <Page title="Homepage">
 <Box p={10} className={classes.root}>
 <Typography variant='h1' color="textPrimary">
 Hello world
 </Typography>
 </Box>
 </Page>
 );
 }
}
export default withStyles(styles)(HomeView);

to show the PDF in Reactjs you can use a tag called embed which looks like this 

<embed id="embededPDF" src={this.state.blobURL} className={classes.pdfView} />

then we will go back to the function which will process the PDF “this.getPDF()” 
We will have to set a configuration variable to contain the responseType as arraybuffer then we will use new Blob to convert the file to Blob type & we can use window.URL.createObjectURL to create a temporary URL for the PDF so the function will look like 

 async getPDF(){
 try{
 // Get the PDF
 let conf = { 
 responseType: 'arraybuffer',
 }
 let res = await axios.get(BackendURL+'/api/files/download/2', conf);
 // Convert our 
 let blob = new Blob([res.data], {type: 'application/pdf'});
 const fileURL = window.URL.createObjectURL(blob);
 //Set the URL of the PDF
 this.setState({ blobURL: fileURL });
 }catch(err){
 console.error(err);
 }
 }

Please note that the PDF should look like this in the Preview of network tab

You can add the authentication

 async getPDF(){
 try{
 // Get the PDF
 let conf = { 
 responseType: 'arraybuffer',
 headers: { Authorization: `Bearer YOUR_TOKEN` }
 }
 let res = await axios.get(BackendURL+'/api/files/download/2', conf);
 console.log(res);
 // Convert our 
 let blob = new Blob([res.data], {type: 'application/pdf'});
 const fileURL = window.URL.createObjectURL(blob);
 this.setState({ blobURL: fileURL });
 }catch(err){
 console.error(err);
 }
 }

The last step adding the Embed tag to the Render

return (
 <Page title="Homepage">
 <Box p={10} className={classes.root}>
 <Typography variant='h1' color="textPrimary">
 Hello world
 </Typography>
 <embed id="embededPDF" src={this.state.blobURL} className={classes.pdfView} />
 </Box>
 </Page>
 );

So the entire component should looks like 

import React from 'react';
import { Box, withStyles, Typography } from '@material-ui/core';
import Page from 'src/components/Page';
import axios from 'axios';
import Loading from 'src/components/Loading';
import { BackendURL } from 'src/constants';

const styles = ({
 root: {
 padding: '90px'
 },
 pdfView:{
 width: '100%',
 height: '900px',
 }
});

class HomeView extends React.Component {

 state = {
 blobURL: null
 };

 async getPDF(){
 try{
 // Get the PDF
 let conf = { 
 responseType: 'arraybuffer',
 headers: { Authorization: `Bearer YOUR_TOKEN` }
 }
 let res = await axios.get(BackendURL+'/api/files/download/2', conf);
 console.log(res);
 // Convert our 
 let blob = new Blob([res.data], {type: 'application/pdf'});
 const fileURL = window.URL.createObjectURL(blob);
 this.setState({ blobURL: fileURL });
 }catch(err){
 console.error(err);
 }
 }

 componentDidMount(){
 this.getPDF();
 }
 
 render(){

 const { classes } = this.props;

 if(!this.state.blobURL){
 return <Loading />
 }

 return (
 <Page title="Homepage">
 <Box p={10} className={classes.root}>
 <Typography variant='h1' color="textPrimary">
 Hello world
 </Typography>
 <embed id="embededPDF" src={this.state.blobURL} className={classes.pdfView} />
 </Box>
 </Page>
 );
 }
}
export default withStyles(styles)(HomeView);

If you have any questions please let me know in the comments below 

Comments

No Comments to show

© 2024 Copyrights reserved for web-brackets.com