Save image from expo assets to user device but first let the user select the target folder

775 views Asked by At

I have researched a lot , even used ChatGTP3 solutions ( which by the way are cool ) but nothing works .


So i will explain my case ( i am targeting android ) :

  1. Inside the local expo assets i have 30 images

enter image description here

i want to allow the user to download this images to his device for whatever reason so i have provided a download button :

enter image description here

When you press the download button i want the user to be able to pick the folder where he wants to save the image and then save it that's it here is an example of many codes i have tried it just doesn't work :

    import * as FileSystem from 'expo-file-system'

    const saveToPhone = async () => {
    try {
        // Assuming that you have a file called '30.jpg' in your Expo assets folder
        const fileUri = Asset.fromModule(require('../../../assets/images/motivational/30.jpg')).uri

        // Let the user pick a folder to save the file to
        const saveDir = await FileSystem.getDocumentDirectoryAsync()

        // Create a new file in the save directory with the same name as the file in assets
        const savePath = `${saveDir}/imageName.jpg`

        // Copy the file from assets to the save directory
        await FileSystem.copyAsync({ from: fileUri, to: savePath })
    } catch (error) {
        console.log(error)
    }
}

I have tried so many codes for days i can't find out how to do that .I am using latest expo sdk 47 .


Update 24/12/2022

After using @proto answer:

import * as FileSystem from 'expo-file-system'
import * as DocumentPicker from 'expo-document-picker'

const saveToPhone = async () => {
  try {
    // Assuming that you have a file called '30.jpg' in your Expo assets folder
    const fileUri = Asset.fromModule(require('../../../assets/images/motivational/30.jpg')).uri

    // Let the user pick a folder to save the file to
    const saveDir = await DocumentPicker.getDocumentAsync()

    // Create a new file in the save directory with the same name as the file in assets
    const savePath = `${saveDir.uri}/imageName.jpg`

    // Copy the file from assets to the save directory
    await FileSystem.copyAsync({ from: fileUri, to: savePath })
  } catch (error) {
    console.log(error)
  }
}

I am getting the following error

 LOG  [Error: Location 'http://192.168.1.13:8081/assets/assets/images/motivational/30.jpg?platform=android&hash=0cf4bfe9c8ccb915c1d43a641d662544?platform=android&dev=true&hot=false' isn't readable.]
1

There are 1 answers

7
pr0to On

You need an additional module called DocumentPicker from expo-document-picker. Instead of getting directory directly, try selecting a document and extract its path.

Something like this :

import * as DocumentPicker from 'expo-document-picker'

const saveDir = await DocumentPicker.getDocumentAsync()
const savePath = `${saveDir.uri}/imageName.jpg`

So now the code should look like this :

import * as FileSystem from 'expo-file-system'
import * as DocumentPicker from 'expo-document-picker'

const saveToPhone = async () => {
  try {
    // Assuming that you have a file called '30.jpg' in your Expo assets folder
    const fileUri = Asset.fromModule(require('../../../assets/images/motivational/30.jpg')).uri

    // Let the user pick a folder to save the file to
    const saveDir = await DocumentPicker.getDocumentAsync()

    // Create a new file in the save directory with the same name as the file in assets
    const savePath = `${saveDir.uri}/imageName.jpg`

    // Copy the file from assets to the save directory
    await FileSystem.copyAsync({ from: fileUri, to: savePath })
  } catch (error) {
    console.log(error)
  }
}