Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cache files when files comes from contents provider #224

Conversation

tkow
Copy link
Contributor

@tkow tkow commented Jul 26, 2019

Closes #70 Closes #206

In android, I found these issues due to using content uri via content provider it restricts access to file without the context or services of application instance. So I fix by saving the files the cache directories.

@tkow tkow force-pushed the feature/cache_files_from_contents_uri branch from a332ed5 to 62617a6 Compare July 26, 2019 14:13
@Elyx0
Copy link
Collaborator

Elyx0 commented Jul 26, 2019

Isn't this risky if the file is too heavy? Do they expire?

@tkow
Copy link
Contributor Author

tkow commented Jul 26, 2019

https://github.com/Elyx0/react-native-document-picker/pull/224/files#diff-523312492e49e2a89c959fc626ac8bcdR209
I use cacheDir and this path's files will be disposed if memory shortage though we should implement handling case of files are purged or limitation size of them, but as I thought, this matters not library but each projects.
See this explanation

@dantman
Copy link
Collaborator

dantman commented Jul 26, 2019

Of course your permissions to a file is time limited and only usable within your application. Even on iOS the native document picker should work that way. The uri provided by a document picker is not supposed to be stored or passed around. You are supposed to get the uri from the picker and then immediately do what you are going to do with the file: upload it, copy it locally and do stuff, or persist permissions if you plan to edit it.

If you are editing the file and want to persist permissions, there is an API to do that:
https://developer.android.com/guide/topics/providers/document-provider#permissions

If you always copy the file into the local cache then you are causing problems for 2/3 of the user use cases for the document picker. People who are uploading the files and do not need the files cached will now have their cache flooded with junk, even if this eventually gets purged it may result in caches that the app does need to make things run fast getting purged faster than they need to. And as for people who are using the document picker to make an editor, because you have copied the file and are returning a file path it is now impossible for them to edit the original file because they absolutely need the content URI to do so.

If you are the 1/3 of use cases and need to copy the file into a local cache, that should be doable at the user level outside of the document picker. i.e. You have the content URI and know immediately when the file has been picked, all you have to do is get the file contents and write them to a local file. RN's fetch() should get you a Blob containing the file's contents (without sending it over the JS bridge), maybe you should see if someone has already written an API that allows you to write that either to your cache path or write a permanent file in your app's data folder if you want persistent access to the copy.

output.write(buffer, 0, read);
}
output.flush();
map.putString(FIELD_URI, file.getPath());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this return a file path instead of a file:// URI breaking consistency with other platforms?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. This has risk if users expect to receive content uri.
Thank you for review.

@tkow
Copy link
Contributor Author

tkow commented Jul 27, 2019

RN's fetch() should get you a Blob containing the file's contents (without sending it over the JS bridge),

I have tried some cases using RNFS or RNFB, but in virtual files from like google drive has permission error. Maybe it is provided content uri from another context calling intent of GET_CONTENT.
I 'll check whether this problem can be resolved and, can I add extra code that optional calling api to cache if this context (or appliction entire permission?) cannot be called from js side? If I find we can resolve this by js only codes. I'll close this PR and I'll post how I do it.

@dantman
Copy link
Collaborator

dantman commented Jul 27, 2019

RNFS is only made to work with the local filesystem, it's not designed to work with documents picked from other apps. RNFB is poorly written and obsolete.

React Native has native support for fetching a content URI to get a Blob.

@tkow
Copy link
Contributor Author

tkow commented Jul 27, 2019

Thank you very much and glad to know that. I'll check this and close this pr today when I have time.

@tkow
Copy link
Contributor Author

tkow commented Jul 27, 2019

I have struggled for a half of day.
#70 (comment)
Do you mean using fetch is like below?

//some async method
const blob = await fetch(contentUri)

I couldn't get no blob though maybe it is possible uploading contents via formData.
So, I still didn't find getting blob to file. This may be due to some library versions or permission setting.

スクリーンショット 2019-07-27 22 22 14

@Elyx0

So I want to add project directory to inspect more easily for everyone in this repository like as other library projects do.
#214
Can I continue setting this pr including android too? These can be excluded npm publish by .npmignore.

my react-native-info

System:
    OS: macOS 10.14.5
    CPU: (12) x64 Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz
    Memory: 3.83 GB / 32.00 GB
    Shell: 5.5.1 - /usr/local/bin/zsh
  Binaries:
    Node: 12.6.0 - ~/.anyenv/envs/nodenv/versions/12.6.0/bin/node
    Yarn: 1.9.4 - /usr/local/bin/yarn
    npm: 6.9.0 - ~/.anyenv/envs/nodenv/versions/12.6.0/bin/npm
  SDKs:
    iOS SDK:
      Platforms: iOS 12.4, macOS 10.14, tvOS 12.4, watchOS 5.3
    Android SDK:
      API Levels: 23, 25, 26, 27, 28
      Build Tools: 27.0.3, 28.0.1, 28.0.3
      System Images: android-28 | Google APIs Intel x86 Atom
  IDEs:
    Android Studio: 3.1 AI-173.4819257
    Xcode: 10.3/10G8 - /usr/bin/xcodebuild
  npmPackages:
    react: ^16.8.6 => 16.8.6
    react-native: ^0.60.4 => 0.60.4

@dantman
Copy link
Collaborator

dantman commented Jul 27, 2019

const blob = await fetch(contentUri)

fetch returns a promise for a response, not a Blob. You need to use .blob() to get the blob. It work the same a fetch on the web.

@tkow tkow changed the title cache files when files comes from contents provder cache files when files comes from contents provider Jul 29, 2019
@tkow
Copy link
Contributor Author

tkow commented Jul 29, 2019

@dantman I confirmed this in my branch #225. Thanks for many advices. I closed this pr.

@tkow tkow closed this Jul 29, 2019
@tkow tkow deleted the feature/cache_files_from_contents_uri branch July 29, 2019 06:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Permission denied selecting google drive file Access Content uri in android
3 participants