DEV Community

Oliver Kem
Oliver Kem

Posted on

File download in React Native and Expo

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

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

Then go to your file, and import the library

import * as FileSystem from 'expo-file-system';
Enter fullscreen mode Exit fullscreen mode

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!!')
        })
}
Enter fullscreen mode Exit fullscreen mode

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

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

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!!')
        })
    }
Enter fullscreen mode Exit fullscreen mode

With this, you are done.
Gracias, see you soon.

Top comments (0)