Download PDF files to device storage with React Native Webview
Tags: javascript, reactnative, webview
Published: 2021-08-15 10:12:59

According to Google search, React Native WebView is a modern, well-supported, and cross-platform WebView for React Native. It is intended to be a replacement for the built-in WebView (which will be removed from core).

Its a component built to enable RN app developers render websites or HyperText Markup Language (HTML) in your RN app, giving the end users nearly the same experience as visiting the website on their native mobile browsers like chrome, Mozilla fire-fox etc  without leaving the application thereby improving user experience. 

Though it has some limitations like handing file download on apple devices which we shall be looking at shortly.



###Getting started with React Native WebView

First you will need to install the library with the command below

```
// with yarn
$ yarn add react-native-webview

// with npm
$ npm install --save react-native-webview
```
please refer to the [official installation guide](https://github.com/react-native-webview/react-native-webview/blob/master/docs/Getting-Started.md) for further step.

I hope you were able to install it  successfully at this point.

Now I will show how to download PDF files to different directories on both iOS and android.

###Basic quickstart with WebView

We will start with the most basic props as we proceed we will add more props from the official documentation where necessary.
 
```
import React, { Component } from 'react';
import {View, Share} from 'react-native';
import * as FileSystem from 'expo-file-system';
import { WebView } from 'react-native-webview';
const { downloadAsync, documentDirectory } = FileSystem;


class MyWeb extends Component {
  render() {
    return (
      <WebView
        source={{ uri: 'https://google.com/' }}
        style={{ marginTop: 20 }}
      />
    );
  }
}
 ```
The source props is a required props that is used to load the web content into the view when its rendered, it could be valid website content loaded over https:// or a local html file defined within the project but for we will focus on downloading files locally for more details on how to load local webpages you can visit [LogRocket.com](https://blog.logrocket.com/the-complete-guide-to-react-native-webview/), the have an amazing content on it.

Next we shall be adding additional props of Webview and code  to enable us download file.

React Native Webview component has [onFileDownload props](https://github.com/react-native-webview/react-native-webview/blob/cb1c3f459f4ccdacec3123f9379d722df1a37e98/docs/Reference.md#onFileDownload) that handles file download for ios alone which we will implement shortly.
```
       <WebView
        source={{
          uri: 'https://www.google.com',
        }}
        ref={webviewRef}
        javaScriptEnabled={true}
        domStorageEnabled={true}
        allowFileAccess={true}
        allowUniversalAccessFromFileURLs={true}
        allowingReadAccessToURL={true}
        mixedContentMode={'always'}
        onFileDownload={({ nativeEvent: { downloadUrl } }) =>
          downloadDocument(downloadUrl);
        }
      />
```
The **downloadDocument function** inside the onFileDownload props callback accepts a param which is the url of the pdf file, downloads it to the app private storage on the device using expo file system, you can use other React Native libraries like **react-native-fs**, **[react-native-fetch-blob](https://www.npmjs.com/package/react-native-fetch-blob)** that supports file download out of the box.

```
let downloadDocument = async (downloadUrl) => {
    let fileURI = await downloadAsync(
      downloadUrl,
      `${documentDirectory}name.pdf`,
      {},
    );
    await onShare(fileURI.uri);
  };

```

Next we shall define **onShare function** that will help us suggest suitable locations like files directory on ios to save our pdf file downloaded and we are done  
  ```
  const onShare = async (url) => {
    try {
      return Share.share({
        message: 'Choose location to save pdf file',
        url: url,
      });
    } catch (error) {
      return error;
    }
  };
```
Please note the following: 

The onFileDownload props is compatible only with ios, it wont work on android.

Android Download Manager handles every webview download out of the box without much tweak or config other than **Write to External permission** that must be requested.

The Content-type of the downlaod url should be set to **application/pdf** in the header config of the server where the file is hosted other wise the downloaded file will have **.bin ext** on android 

The code snippet was tested and worked for pdf files both on android/ios devices, to download png/jpeg/jpg please use media storage instead.