Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View a PDF in React Native

Can anyone please provide sample code for displaying a PDF in React Native? iOS and Android.

This is what I've tried:

  render: function() {     return <WebView       source={require('./my.pdf')}       />   } 

^ This results in a Red Screen of Death with the "Unable to resolve module" error.

  render: function() {     return <WebView       source={{uri: 'my.pdf'}}       />   } 

^ This gives an "Error Loading Page" message in the WebView. "The requested URL was not found on this server"

I know iOS is capable of showing a PDF in a UIWebView. I assume Android can do the same. There must be something in how the source is specified that I'm missing.

like image 297
Axeva Avatar asked Mar 09 '16 18:03

Axeva


People also ask

How do I make a PDF in React Native?

The simplest way to create a PDF document in a React Native project includes the use of Expo Print plugin. The first step is to write HTML with a sample of content that should be in our PDF. You can insert CSS styles, custom fonts, images, links, etc to your markup.


2 Answers

Okay, for future generations, here's how I solved this problem:

Updated September 13, 2017:

There is a new NPM module that makes this entire process much easier. I would suggest using it going forward instead of my original answer below:

react-native-pdf

Once installed, rendering the PDF is as easy as this:

export default class YourClass extends Component {   constructor(props) {     super(props);     this.pdf = null;   }    render() {     let yourPDFURI = {uri:'bundle-assets://pdf/YourPDF.pdf', cache: true};      return <View style={{flex: 1}}>       <Pdf ref={(pdf)=>{this.pdf = pdf;}}         source={yourPDFURI}         style={{flex: 1}}         onError={(error)=>{console.log(error);}} />     </View>   } } 

Just put your actual pdf in the android/app/src/main/assets/pdf folder of your project.

Original Answer:

iOS

render: function() {   return <WebView source={{uri: 'My.pdf'}}/> } 

The trick is that you need to include My.pdf into your project in Xcode and make sure it's added to your build target.

Just copying it into your React Native project folder wasn't enough. It had to be part of the Xcode project itself.

Android

It appears that Android did not provide a native PDF viewer until 5.0 (Lollipop). To get around this, I've had to make use of three key techniques:

  1. Pull the PDF out of my APK bundle and store it in the files folder for my app. This SO answer was very helpful in accomplishing this:

Android: How to copy files from 'assets' folder to sdcard?

I tweaked the code a bit so that the file wasn't going to an sdcard but to my app's files folder. Here's what I added to my MainActivity.java

@Override protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);    AssetManager assetManager = getAssets();   String[] files = null;    try {       files = assetManager.list("pdf");   } catch (IOException e) {       Log.e("tag", "Failed to get asset file list.", e);   }    if (files != null) for (String filename : files) {       InputStream in = null;       OutputStream out = null;        try {         in = assetManager.open("pdf/" + filename);          File outFile = new File(getFilesDir(), filename);         out = new FileOutputStream(outFile);         copyFile(in, out);         Log.e("tag", "Copy was a success: " + outFile.getPath());       } catch(IOException e) {         Log.e("tag", "Failed to copy asset file: " + "pdf/" + filename, e);       }       finally {           if (in != null) {               try {                   in.close();               } catch (IOException e) {                   // NOOP               }           }           if (out != null) {               try {                   out.close();               } catch (IOException e) {                   // NOOP               }           }       }   } }  private void copyFile(InputStream in, OutputStream out) throws IOException {     byte[] buffer = new byte[1024];     int read;     while((read = in.read(buffer)) != -1){       out.write(buffer, 0, read);     } } 

I also made sure my PDF is in the assets/pdf folder under android/app/src/main

  1. I then utilized the react-native-fs package to get the absolute URL to my PDF, which is now in the files folder:

    var RNFS = require('react-native-fs'); var absolutePath = RNFS.DocumentDirectoryPath + '/My.pdf'; 
  2. With all of this in place, I used react-native-pdf-view to actually load and display the PDF:

    import PDFView from 'react-native-pdf-view';  render: function() {   var absolutePath = RNFS.DocumentDirectoryPath + '/My.pdf';    return <PDFView     ref={(pdf)=>{this.pdfView = pdf;}}     src={absolutePath}     style={ActharStyles.fullCover} /> } 

Good luck!

like image 93
Axeva Avatar answered Sep 17 '22 17:09

Axeva


A simple solution for this problem is to set <WebView> source/uri to this:

https://drive.google.com/viewerng/viewer?embedded=true&url={your pdf url}’ 
like image 25
Michael Falck Wedelgård Avatar answered Sep 21 '22 17:09

Michael Falck Wedelgård