androidreact-nativeexpo

Expo React Native, saving PDF files to Downloads folder


The following code works correctly for image files. But when I'm trying to save PDF file or other not-media formates, I get Could not create asset error.
I understand that expo-media-library is designed to work with media format files. Is there any alternative for expo-media-library to save other files formats?

import * as FileSystem from 'expo-file-system'
import * as Permissions from 'expo-permissions'
import * as MediaLibrary from 'expo-media-library'

const downloadFile = async (uri: string) => {
    const targetUri = FileSystem.documentDirectory + getFileName(uri)

    const downloadedFile = await FileSystem.downloadAsync(uri, targetUri)

    if (downloadedFile.status === 200) {
        if (Platform.OS === 'android') {
            const permission = await Permissions.askAsync(Permissions.MEDIA_LIBRARY)

            if (permission.status !== 'granted') {
                return
            }

            const asset = await MediaLibrary.createAssetAsync(downloadedFile.uri)
            const album = await MediaLibrary.getAlbumAsync('Download')

            await MediaLibrary.addAssetsToAlbumAsync([asset], album, false)
        }
    }
}

Solution

  • it works on android device with https://docs.expo.dev/versions/latest/sdk/filesystem/#storageaccessframeworkcreatefileasyncparenturi-string-filename-string-mimetype-string

    import * as FileSystem from 'expo-file-system';
    import { StorageAccessFramework } from 'expo-file-system';
    
    const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync();
    if (!permissions.granted) {
        return;
    }
    
    try {
        await StorageAccessFramework.createFileAsync(permissions.directoryUri, fileName, 'application/pdf')
        .then((r) => {
            console.log(r);
        })
        .catch((e) => {
            console.log(e);
        });
    } catch((e) => {
        console.log(e);
    });
    

    My pdf is well downloaded !

    In my case i had to generate the file from a base64 string. My code :

    import * as FileSystem from 'expo-file-system';
    import { StorageAccessFramework } from 'expo-file-system';
    
    const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync();
    if (!permissions.granted) {
        return;
    }
    
    const base64Data = 'my base 64 data';
    
    try {
        await StorageAccessFramework.createFileAsync(permissions.directoryUri, fileName, 'application/pdf')
            .then(async(uri) => {
                await FileSystem.writeAsStringAsync(uri, base64Data, { encoding: FileSystem.EncodingType.Base64 });
            })
            .catch((e) => {
                console.log(e);
            });
    } catch (e) {
        throw new Error(e);
    }