File download in React Native and Expo
Tags: reactnative, mobile, android, ios
Published: 2023-05-20 12:12:01

Hello, today I am going to show us how you can can save files in React Native. If you are fetching a file from the backend server through an API endpoint, you will need to find a way to save the files to your phone. With this, you will have to figure out how you can handle permissions to access the files. I want to show you how you can handle permissions in React Native. I am using Expo.
After trying ``rn-fetch-blob`` and other libraries, I found out that they are not compatible with expo. (Only React Native CLI)

We have to consider about file system access and permissions.
After setting up a React Native Application and Adding a button. Let as get started, go to your terminal then type:

```
yarn add axios
```
I will be using axios to fetch the resource. Since expo is so strict with installing some files, I will be installing the libraries using expo. We are going to install ``expo-file-system`` library.

```
npx expo install expo-file-system
```
Then go to your file, and import the library

```
import * as FileSystem from 'expo-file-system';
```
Now, we write a function to fetch the resource.

```
async function fetchReportForm(fileType: string){
		
        axios.post(`https://resource.url`).then(async(res)=>{
            const pdfData = res.data;
        })
        .catch((err)=>{
			Alert.alert('Error','Error Downloading File!!')
        })
}
```
Now, we write a function to fetch the resource that helps us with file permissions.

```
const requestFileWritePermission =async () => {
		const permissions = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();
		console.log(permissions.granted);
		if (!permissions.granted) {
                     Alert.alert('Error','File Permissions Denied')
			return {
				access: false,
				directoryUri: null
			};
		}
		return {
			access:true,
			directoryUri: permissions.directoryUri
		};
	}
```
With this, the user will be prompted with a request for directory to download the file, it then returns an object with the directory uri to save the file to. Now, we will be using thi directory uri to save the file.
Now let's write a function to help us save the file to our file system.

```
import * as FileSystem from 'expo-file-system';
const saveReportFile = async (pdfData: any,directoryUri: string)=>{
		try {
			await FileSystem.StorageAccessFramework.createFileAsync(directoryUri, 'My_file', 'application/pdf')
			.then(async(uri) => {
				await FileSystem.writeAsStringAsync(uri, pdfData, { encoding: FileSystem.EncodingType.Base64 });
			}).then(res=>{
				console.log(res)
				Alert.alert('Success', `File Saved`)
			})
			.catch((e) => {
				console.log(e);
			});
		} catch (error) {
			Alert.alert('Error',`Could not Download file ${error.message}`);
		}
	}
```
The function takes 2 inputs pdfData and the directoryUri to save the file. I passed the ``My_file`` as the file name.
Now, let us bundle up the whole code.

```
const requestFileWritePermission =async () => {
		const permissions = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();
		console.log(permissions.granted);
		if (!permissions.granted) {
			console.log('File write Permissions Denied!!')
			return {
				access: false,
				directoryUri: null
			};
		}
		return {
			access:true,
			directoryUri: permissions.directoryUri
		};
}
const saveReportFile = async (pdfData: any,directoryUri: string)=>{
		try {
			await FileSystem.StorageAccessFramework.createFileAsync(directoryUri,'My_file', 'application/pdf')
			.then(async(uri) => {
				await FileSystem.writeAsStringAsync(uri, pdfData, { encoding: FileSystem.EncodingType.Base64 });
			}).then(res=>{
				console.log(res)
				Alert.alert('Success', `File Saved`)
			})
			.catch((e) => {
				console.log(e);
			});
		} catch (error) {
			Alert.alert('Error',`Could not Download file ${error.message}`);
		}
	}
    async function fetchReportForm(fileType: string){
		console.log('Attempting to Download file: ', fileType,'Report is',reportToDownload.stream);
        axios.post(``).then(async(res)=>{
            const pdfData = res.data;
			const hasPermissions = await requestFileWritePermission();
			if (hasPermissions.access) {
				saveReportFile(pdfData, hasPermissions.directoryUri)
			}
        })
        .catch((err)=>{
			console.log(err)
			Alert.alert('Error','Error Downloading File!!')
        })
    }
```
With this, you are done.
Gracias, see you soon.