alpha0010 / react-native-file-access

Filesystem access for React Native
MIT License
307 stars 19 forks source link

feat: Custom external directory #10

Closed Marvedog closed 3 years ago

Marvedog commented 3 years ago

Have you considered adding to cpExternal the possibility to copy to a custom directory? E.g. to copy a file not to Downloads, but to My-Awesome-name.

alpha0010 commented 3 years ago

Two types of data apps tend to have are internal managed (database, cache, etc.) and system managed (pictures, videos, etc. that should be visible to all apps on the device). cpExternal() is intended for the later. They are system defined locations, so all apps (if granted permission) can share the media.

What would the goal of a custom directory be? No other app would know to look for it. If just trying to use folders to organize internally, something like FileSystem.mkdir(Dirs.DocumentDir + '/subfolder'), then write files to that folder.

Or am I missing your goal?

Marvedog commented 3 years ago

yeah, kinda. The purpose is not for other apps to be able to find it, but to simplify the discovery process for end-users. We use this repo to download PDFs to the end-users' external storage such that they can retrieve it and use it for whatever purpose they want. The argument is just that it may be simpler to find the document in a My-app-name folder than to dig into the downloads folder.

alpha0010 commented 3 years ago

Thinking about how to implement; might be a bit tricky regarding what makes sense cross-platform.

alpha0010 commented 3 years ago

Try Dirs.SDCardDir. Use it as a normal path (make subdirectories, write files, etc.). Note that it may be null/undefined if the path cannot be determined.

mitchdowney commented 2 years ago

@alpha0010 sorry to bug you, but I struggled with scoped storage all day, and I'm wondering if you could see some obvious mistake I'm making with my process...

I'm trying to copy to the scoped storage "Podcasts" directory on an SD card, but I get an error like follows:

Error: /tree/01F6-AC3F:Podcasts/document/01F6-AC3F:Podcasts/7kJmAzNQ3.mp3: open failed: ENOENT (No such file or directory)

Here's basically the sequence of steps I'm doing to get there...

First, I requested permission to the SD card Podcasts directory using:

import * as ScopedStorage from 'react-native-scoped-storage'
...
  _setExtDownloadFileLocationAndroid10 = async () => {
    const dir = await ScopedStorage.openDocumentTree(true)

    if (dir?.uri?.endsWith('%3APodcasts')) {
      const sdCardDownloadLocation = dir.uri
      await AsyncStorage.setItem(PV.Keys.EXT_STORAGE_DLOAD_LOCATION, sdCardDownloadLocation)  
      ...
    }
  ...
}

Then, on file download using react-native-background-downloader, I download to origDestination, then try to move it into scoped storage:

  const folderPath = RNFS.TemporaryDirectoryPath
  const origDestination = `${folderPath}/${episode.id}${ext}`
  // download the episode from origDestination using react-native-background-downloader
  ...
  // then in the `done` callback, I try to move the file into scoped storage:
  const sdDestination = `${sdCardDownloadLocation}/${episode.id}.mp3`
  await FileSystem.cp(origDestination, sdDestination)
...

However...when I do that I get:

Error: /tree/01F6-AC3F:Podcasts/document/01F6-AC3F:Podcasts/7kJmAzNQ3.mp3: open failed: ENOENT (No such file or directory)

There must be something fundamental I'm missing about this process...does that make sense, and do you have any advice on how to accomplish this?

alpha0010 commented 2 years ago

@mitchdowney Could you open a new issue with this? It makes it easier for me to track.

Have you looked around the device to see if you can find the .mp3 somewhere? https://developer.android.com/studio/debug/device-file-explorer