GithubHelp home page GithubHelp logo

Comments (11)

ambessh avatar ambessh commented on July 28, 2024

@mitchdowney yes it is possible.

copyfile takes three arguments
uri of source
uri of destination
and callback

make sure you provide uri only not path . and the uri should not be document tree selected uri

from react-native-scoped-storage.

ammarahm-ed avatar ammarahm-ed commented on July 28, 2024

Update to 1.9.3. it supports reading and writing to normal paths such as cache and data directory.

from react-native-scoped-storage.

mitchdowney avatar mitchdowney commented on July 28, 2024

@ambessh hmm I have 1.9.3 installed, and I'm not sure what I'm doing wrong then...

When I call this:

const result = await ScopedStorage.stat('file://data/user/0/com.podverse/files/_qhiTuJQT.mp3')

I get:

Error: 'file://data/user/0/com.podverse/files/_qhiTuJQT.mp3'does not have permission to read/write

Is that an invalid uri? (that is the RNFS.DocumentDirectoryPath btw)

Also, the copyFile call I am attempting is:

await ScopedStorage.copyFile(`file://data/user/0/com.podverse/files/6NvramAVN.mp3`, content://com.android.externalstorage.documents/tree/01F6-AC3F%3APodcasts/document/01F6-AC3F%3APodcasts/6NvramAVN.mp3, () => {})

That doesn't throw an error, but the file doesn't get saved to the SD card either...is there anything you can see I'm doing wrong? I'm not using a callback, but I'm not sure I need to?

from react-native-scoped-storage.

AZKZero avatar AZKZero commented on July 28, 2024

@ambessh hmm I have 1.9.3 installed, and I'm not sure what I'm doing wrong then...

When I call this:

const result = await ScopedStorage.stat('file://data/user/0/com.podverse/files/_qhiTuJQT.mp3')

I get:

Error: 'file://data/user/0/com.podverse/files/_qhiTuJQT.mp3'does not have permission to read/write

Is that an invalid uri? (that is the RNFS.DocumentDirectoryPath btw)

Also, the copyFile call I am attempting is:

await ScopedStorage.copyFile(`file://data/user/0/com.podverse/files/6NvramAVN.mp3`, content://com.android.externalstorage.documents/tree/01F6-AC3F%3APodcasts/document/01F6-AC3F%3APodcasts/6NvramAVN.mp3, () => {})

That doesn't throw an error, but the file doesn't get saved to the SD card either...is there anything you can see I'm doing wrong? I'm not using a callback, but I'm not sure I need to?

+1

from react-native-scoped-storage.

ambessh avatar ambessh commented on July 28, 2024

@mitchdowney during copy file i had the same issue . it was not saving it and the callback was returning nothing.
Go to -> node modules/react-native-scoped-storage/android/src/main/java/com/amaarahmed/scopedstorage/RNScopedStorageModule.java
search copyFile function in that java file and replace with this

@ReactMethod
 public void copyFile(String path, String dest, Callback callback) {
     String pathToUri = Uri.fromFile(new File(path)).toString();
     AsyncTask.execute(() -> {
             
         InputStream in = null;
         OutputStream out = null;
         String message = "";

         try {
             if (!exists(pathToUri)) {
                 message = "Source file does not exist";
                 callback.invoke((message));
                 return;
             }
             ParcelFileDescriptor inputDescriptor = reactContext.getContentResolver().openFileDescriptor(Uri.parse(pathToUri), "rw");
             in = new FileInputStream(inputDescriptor.getFileDescriptor());

             if (!exists(dest)) {
                 message = "Destination file does not exist. Please create destination file with createFile.";
                 callback.invoke((message));
                 return;
             }

             ParcelFileDescriptor outputDescriptor = reactContext.getContentResolver().openFileDescriptor(Uri.parse(dest), "rw");
             out = new FileOutputStream(outputDescriptor.getFileDescriptor());

             byte[] buf = new byte[10240];
             int len;
             while ((len = in.read(buf)) > 0) {
                 out.write(buf, 0, len);
             }
         } catch (Exception err) {
             message += err.getLocalizedMessage();
         } finally {
             try {
                 if (in != null) {
                     in.close();
                 }
                 if (out != null) {
                     out.close();
                 }
             } catch (Exception e) {
                 message += e.getLocalizedMessage();
             }
         }

         if (message != "") {
             callback.invoke(message);
         } else {
             callback.invoke();
         }
    
    
    });

     

     
 }

and now in react javascript dont pass uri in the first argument of copyfile function . just pass normal path . It will work.
laters you can create a patch of the package.

from react-native-scoped-storage.

mitchdowney avatar mitchdowney commented on July 28, 2024

@ammarahm-ed I tried your code, updated RNScopedStorageModule.java (verified the changes are used in the react native app), then call this:

await ScopedStorage.copyFile("/storage/emulated/0/Download/lwx0wMYSjP.mp3", "content://com.android.externalstorage.documents/tree/01F6-AC3F%3APodverse/document/01F6-AC3F%3APodverse/lwx0wMYSjP.mp3", (msg) => {
  console.log('ScopedStorage.copyFile msg', msg)
})

But then I get:

ScopedStorage.copyFile msg Failed to open for writing: java.io.FileNotFoundException: open failed: EISDIR (Is a directory)

Any ideas what the "EISDIR is a directory" is about? That path and uri does not seem like a directory to me...

I also tried this:

await ScopedStorage.createFile("content://com.android.externalstorage.documents/tree/01F6-AC3F%3APodverse/document/01F6-AC3F%3APodverse/", `${episode.id}${ext}`, 'audio/mpeg')
await ScopedStorage.copyFile("/storage/emulated/0/Download/lwx0wMYSjP.mp3", "content://com.android.externalstorage.documents/tree/01F6-AC3F%3APodverse/document/01F6-AC3F%3APodverse/lwx0wMYSjP.mp3", (msg) => {
  console.log('ScopedStorage.copyFile msg', msg)
})

And I verified the file is created as expected...but I still get the "is a directory" error.

from react-native-scoped-storage.

mitchdowney avatar mitchdowney commented on July 28, 2024

@ammarahm-ed eureka! copyFile works for me is I use the uri:

content://com.android.externalstorage.documents/tree/01F6-AC3F%3APodverse/document/01F6-AC3F%3APodverse%2Flwx0wMYSjP.mp3

With the URL encoded %2F character instead of /. Not sure why it's necessary...but it's finally saving to the SD card! Thank you for your help 🙏

from react-native-scoped-storage.

mitchdowney avatar mitchdowney commented on July 28, 2024

@ammarahm-ed ahhh...but there's a bug with this...

It seems like the %2F sometimes works, and sometimes throws a "ENOENT No such file or directory" error:

Works:

content://com.android.externalstorage.documents/tree/01F6-AC3F%3APodcasts/document/01F6-AC3F%3APodcasts%2Fesgi0q1Pm.mp3
content://com.android.externalstorage.documents/tree/01F6-AC3F%3APodcasts/document/01F6-AC3F%3APodcasts%2FuJbRmLuc0.mp3

Fails with ENOENT error:

content://com.android.externalstorage.documents/tree/01F6-AC3F%3APodcasts/document/01F6-AC3F%3APodcasts%2FGwHcavR3a.mp3
content://com.android.externalstorage.documents/tree/01F6-AC3F%3APodcasts/document/01F6-AC3F%3APodcasts%2F6gWMTVqam.mp3

I guess there is some kind of URL encoded clash, depending on the first character of the file id?

from react-native-scoped-storage.

ambessh avatar ambessh commented on July 28, 2024

@mitchdowney pls dont hardcode it . Get uri from when you create the file .

from react-native-scoped-storage.

mitchdowney avatar mitchdowney commented on July 28, 2024

@ambessh I was getting very buggy and inconsistent results with this...but I think it may have been conflicts caused by identical files already existing in the temporary DocumentDirectoryPath from previous test downloads.

After wiping the app completely and deleting all data, this code seems to work consistently when run in the react-native-background-downloader done method:

if (customLocation) {
    const tempDownloadFileType = await ScopedStorage.stat(origDestination)
    const newFileType = await ScopedStorage.createFile(customLocation, `${episode.id}${ext}`, 'audio/mpeg')
    if (tempDownloadFileType && newFileType) {
      const { uri: tempFileUri } = tempDownloadFileType
      const { uri: newFileUri } = newFileType
      await ScopedStorage.copyFile(tempFileUri, newFileUri, (msg) => {
        console.log('ScopedStorage.copyFile msg', msg)
      })
      await ScopedStorage.deleteFile(tempFileUri)
    }
}

HOWEVER, stat throws a "cannot read/write" permissions error. I had to go into the RNScopedStorageModule and modify the hasPermission function so that it always returns true. This is obviously no good...but why is read/write permission even needed for the DocumentDirectoryPath? Shouldn't it only be "read" permission that is needed? And isn't this a path that we should be able to read/write to by default anyway, even with scoped storage?

It appears the problem is that DocumentDirectoryPath is not returned by the getPersistedUriPermissions function. It seems crazy though if I have to tell the user to somehow manually allow writes to the DocumentDirectoryPath.

ALSO: deleteFile is failing. It says:

Error: Invalid URI: /storage/emulated/0/Android/data/com.podverse/files/M6FsE-t6d.mp3

What's odd to me is this is the URI that is returned by the stat function...so something seems wrong there.

from react-native-scoped-storage.

Rohitbarate avatar Rohitbarate commented on July 28, 2024

@ammarahm-ed eureka! copyFile works for me is I use the uri:

content://com.android.externalstorage.documents/tree/01F6-AC3F%3APodverse/document/01F6-AC3F%3APodverse%2Flwx0wMYSjP.mp3

With the URL encoded %2F character instead of /. Not sure why it's necessary...but it's finally saving to the SD card! Thank you for your help 🙏

hey bro , i am facing issue "source file not exist" and i used this uri : 'content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fmedia%2Fcom.whatsapp%2FWhatsApp%2FMedia%2F.Statuses/document/primary%3AAndroid%2Fmedia%2Fcom.whatsapp%2FWhatsApp%2FMedia%2F.Statuses%2F'
and this is my copy file function = const copyFileFunction = async (sourceUrl, destUrl) => { const fileStat = await ScopedStoragePackage.stat(sourceUrl) console.log({fileStat}); await ScopedStoragePackage.copyFile(fileStat.uri,destUrl,(res)=>{console.log({res});}) };
could you pls tell me where i am wrong ?
Screenshot 2023-07-20 120458

from react-native-scoped-storage.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.