Downloading and Displaying a file in React Native
Tags: reactnative, firstpost, typescript, javascript
Published: 2021-02-22 21:12:17

React Native does not currently offer full support for downloading and showing a file. The approach in this article shows you how to download and display a file using the [react-native-fs](https://github.com/itinance/react-native-fs) and [react-native-webview](https://github.com/react-native-webview/react-native-webview) libraries respectively.

In this example, the file is of a PDF format, however, the same approach can be used for images or other text file formats.

###Prerequisites:
A working React Native App. Not sure how to do this? Checkout the setup instructions on the [React Native Website](https://reactnative.dev/docs/getting-started).

##Downloading the file
###Install react-native-fs:
```
yarn add react-native-fs
```
or
```
npm install react-native-fs
```
If you're using React Native version 0.60.0 or higher, it a does auto-linking for you. If not, check the extra setup instructions on react-native-fs page.
Install the CocoaPods dependencies (iOS specific):
```
cd ios && pod install
```


###Using downloadFile function:
In this example, I will be retrieving a PDF file from an API endpoint using the downloadFile function from `react-native-fs`. This function has two required parameters - fromUrl and toFile , along with several other optional ones. I created an async function downloadPDF which requires a url and fileName. It also contains a basic header with an authorization token and content-type.

React-native-fs' DocumentDirectoryPath provides the Android or iOS where documents are stored. You can change this to your customised path if you wish.
```javascript
downloadPDF = async (url: string, fileName: string): Promise<any> =>{
//Define path to store file along with the extension
const path = `${DocumentDirectoryPath}/${fileName}.pdf`;
const headers = {
  'Accept': 'application/pdf',
  'Content-Type': 'application/pdf',
  'Authorization': `Bearer [token]`
}
//Define options
const options: DownloadFileOptions = {
  fromUrl: [baseUrl] + url,
  toFile: path,
  headers: headers
}
//Call downloadFile
const response =  await downloadFile(options);
return response.promise.then(async res => 
  //Transform response
  if(res && res.statusCode === 200 && res.bytesWritten > 0 &&
  res.path){
    doSomething(res)
  }else{
    logError(res)
}};
```
The response from downloadFile contains `statusCode` , `jobId` and `bytesWritten` . To know if a request is successful, check whether the `statusCode` is `200` and the `bytesWritten` > `0`. It is important to check both values because, I found it returning 200 even when no files were written.

I saved the `path` in the Redux's `state` to later retrieve the file.

##Opening the saved file in a WebView
###Install react-native-webview:
```
yarn add react-native-webview
```
or
```
npm install react-native-webview
```
Again, install the CocoaPods dependencies (iOS specific):
```
cd ios && pod install
```

###Implementing the WebView:
Create a React Funcional Component containing a WebView .
```javascript
const WebViewComponent: React.FunctionComponent = ({ navigation, route}: any): JSX.Element => (
<WebView
  source={{ uri: "file://"+ path}}
  style={{ flex: 1 }}
  originWhitelist={["*"]}
/>
)};
export default WebViewComponent;
```
The WebView source's URI should point to `file://` + `pathToFile` . Don't forget to include the `style` property and set `flex:1` as shown above.