DEV Community

Cover image for Download PDF files to device storage with React Native Webview
Obeya Edward Obande
Obeya Edward Obande

Posted on • Edited on

Download PDF files to device storage with React Native Webview

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
Enter fullscreen mode Exit fullscreen mode

please refer to the official installation guide 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 }}
      />
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

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, 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 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);
        }
      />
Enter fullscreen mode Exit fullscreen mode

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 that supports file download out of the box.

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

Enter fullscreen mode Exit fullscreen mode

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;
    }
  };
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (2)

Collapse
 
syntx1997 profile image
Harley Ferrer Lumagui • Edited

I have followed your instructions but it gives me this error, how could I fix this?

The "EXNativeModulesProxy" native module is not exported through NativeModules; verify that expo-modules-core's native code is
linked properly
App@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false&app=com.timbangapp&modulesOnly=false&runModule=true:107055:65
RCTView
View
RCTView
View
AppContainer@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false&app=com.timbangapp&modulesOnly=false&runModule=true:74969:36

Collapse
 
obie3 profile image
Obeya Edward Obande • Edited

Hi Harley, sorry for the silence, quick one, re you using expo framework to build your app?