Reputation: 33
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)
}
}
}
Upvotes: 3
Views: 13880
Reputation: 1
For anyone else looking this is also what worked on my side for PDF-s:
import { Alert } from "react-native";
import * as IntentLauncher from "expo-intent-launcher";
export const handleOpenPdf = async (imageUrl) => {
if (!imageUrl) {
Alert.alert("...");
return;
}
try {
await IntentLauncher.startActivityAsync("android.intent.action.VIEW", {
data: imageUrl,
type: "application/pdf",
});
} catch (error) {
console.error("Failed to open PDF:", error);
Alert.alert("...");
} finally {
//add logic
}
};
Upvotes: 0
Reputation: 1
The permission can be persisted by storing the path. Here is how
Code to save/get the path from storage :
const savePermissionGrantedFolderURI = async (uri: string) => {
await AsyncStorage.setItem("granted-permission-folder", uri);
};
export const getPermissionGrantedFolderURI = async () => {
return await AsyncStorage.getItem("granted-permission-folder");
};
Code to check and get permission granted folder's uri :
const checkAndGetPermissionGrantedFolderURI = async() => {
// get the uri if the permission is already granted
const uri = await getPermissionGrantedFolderURI();
if (uri) {
// find if the uri is still valid
try {
const fileInfo = await FileSystem.StorageAccessFramework.readDirectoryAsync(uri);
if (Array.isArray(fileInfo)) {
return uri;
}
} catch (error) {
// if not found or invalid, get the permission again by continuing
}
}
// if not found or invalid, get the permission again
const permissions =
await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();
if (permissions.granted) {
// save the permission granted folder uri and return the uri
await savePermissionGrantedFolderURI(permissions.directoryUri);
return permissions.directoryUri;
}
// if permission is not granted
return null;
};
Code to check platform and write file if its android :
const saveFileToDevice = async(
uri: string, // or base64
filename: string,
mimetype: string
) => {
if (Platform.OS === "android") {
const permissionGrantedURI = await checkAndGetPermissionGrantedFolderURI();
if (!permissionGrantedURI) return;
// if you have base64 already skip this step
const base64 = await FileSystem.readAsStringAsync(uri, {
encoding: FileSystem.EncodingType.Base64,
});
const fileOnDeviceURI = await FileSystem.StorageAccessFramework.createFileAsync(
permissionGrantedURI,
filename,
mimetype
);
await FileSystem.writeAsStringAsync(fileOnDeviceURI, base64, {
encoding: FileSystem.EncodingType.Base64,
});
// if the file is saved successfully, return true
return true;
}
await shareAsync(uri);
};
Upvotes: 0
Reputation: 186
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);
}
Upvotes: 5