react-native-fetch-blob icon indicating copy to clipboard operation
react-native-fetch-blob copied to clipboard

Read file from Camera roll (content:// path on android)

Open nordved opened this issue 7 years ago • 51 comments

I am trying to get the base64 code for an image in the camera roll. The path for the image is something like

content://com.app.provider/app_images/Android/data/com.app/files/Pictures/image-a00a13f4-a24f-40ce-bb16-e56979b75692.jpg

And I am trying to read this file with

RNFetchBlob.fs.readFile(localPath, 'utf8')

and

RNFetchBlob.fs.readFile(localPath, 'base64')

The app simply crashes and in the logcat I can find the error

Column '_data' does not exist

I have also tried

RNFetchBlob.fs.readFile(RNFetchBlob.wrap(localPath), 'base64')

Which gives the error:

Error: Attempt to invoke virtual method 'boolean java.lang.String.startsWith(java.lang.String)' on a null object reference

In the FileSystem API you write that it is possible to read the files from content://, so I'd like to know if there is another way that I'm not seeing.

EDIT: I'm using RN 0.41 and RNFB 0.10.2

nordved avatar Mar 14 '17 15:03 nordved

I'm seeing the same thing for readFile calls to paths within DocumentDir.

Error: Attempt to invoke virtual method 'boolean java.lang.String.startsWith(java.lang.String)' on a null object reference
    at createErrorFromErrorData (NativeModules.js:116)
    at NativeModules.js:79
    at MessageQueue.__invokeCallback (MessageQueue.js:288)
    at MessageQueue.js:127
    at guard (MessageQueue.js:46)
    at MessageQueue.invokeCallbackAndReturnFlushedQueue (MessageQueue.js:126)
    at debuggerWorker.js:71

Android, RN 0.42.

tlvince avatar Mar 15 '17 00:03 tlvince

I just found this today. So that's a +1 from me. Specifically, it's when sharing from Google Drive which give's a URI looking like... content://com.google.android.apps.docs.storage.legacy/enc%3D2cnEPvlNW2uZUjq8h_w7hhNWmkRhsPqHum9gJTxeOrsaGiV3%0A

Same error pops up, and get's caught in the promise. Error processing message Error: Attempt to invoke virtual method 'boolean java.lang.String.startsWith(java.lang.String)' on a null object reference

Should mention I'm using the readFile(uri, 'base64') version. Also: RN: 0.35.0 RNFetchBlob: 0.10.0

chris-pikul avatar Mar 20 '17 16:03 chris-pikul

Thanks for providing the information, will look into this issue ASAP 👍

wkh237 avatar Mar 21 '17 01:03 wkh237

After some investigation, the problem is that our Android URI resolver couldn't get the absolute file path from the given URI. I will try to figure out if there's a better implementation.

wkh237 avatar Mar 22 '17 05:03 wkh237

I'm experiencing this in Android 7.1 if that makes any difference. Lmk if you'd like me to test anything.

tlvince avatar Mar 22 '17 07:03 tlvince

@ChrisPikul510 @tlvince , is there any way to make a content provider URI like content://com.app.provider/app_images/Android/data/com.app/files/Pictures/image-a00a13f4-a24f-40ce-bb16-e56979b75692.jpg and content://com.google.android.apps.docs.storage.legacy/enc%3D2cnEPvlNW2uZUjq8h_w7hhNWmkRhsPqHum9gJTxeOrsaGiV3%0A ?

In my case, the URIs from camera roll look like this content://media/external/images/media/694, and there's no problem to resolve this kind of URI.

wkh237 avatar Mar 23 '17 02:03 wkh237

Apologies. In my case I'd missed adding a content type prefix altogether; adding file:// to e.g. file://${RNFetchBlob.fs.dirs.DocumentDir}/${filename} works for me.

tlvince avatar Mar 23 '17 17:03 tlvince

@wkh237 I was using https://github.com/marcshilling/react-native-image-picker to take a picture. It saves to the gallery of the phone or selects from the gallery. I can understand if you feel like 3rd party support is not on the top of your list though.

I solved it by storing the base64 directly from the callback instead of getting it from the filesystem.

nordved avatar Mar 23 '17 19:03 nordved

@nordved , thanks for the information. It'd be great to make this kind of URI supported since it's very common use case IMO 👍

wkh237 avatar Mar 24 '17 02:03 wkh237

@wkh237 The uri I was attempting came directly from Google Drive app through a share intent. In which case from my end I'm not entirely sure exists as that looks like a hash/temp URI. Are you suggesting I modify the URI?

BTW, is there a way you can implement a function for grabbing N bytes from a file? I ask because I'm only reading this file to grab the first 16 bytes to cross-reference with my list. Which also if you want to integrate here would be cool too. It's just header signature negotiation... https://github.com/ChrisPikul510/content-type-negotiation

chris-pikul avatar Mar 25 '17 11:03 chris-pikul

@ChrisPikul510 , thanks for the information, though the function is not supported yet but it's on our roadmap (see #124).

However, as a workaround, you can use an undocumented API fs.slice this API will not be removed as it's used by Blob.slice polyfill.

fs.slice(src:string, dest:string, start:number, end:number):Promise 

which will create a file at path dest you can then read its content via fs.readFile.

wkh237 avatar Mar 26 '17 14:03 wkh237

@wkh237 So if I have this right, a way for me to get the header is to do something like....

RNFetchBlob.fs.slice('file://some/file', CACHE_DIR_FILE, 0, 16)
   .then(() => RNFetchBlob.fs.readFile(CACHE_DIR_FILE, 'base64'))
   .then((data) => {
      //Do something with data
   })
   .catch(console.warn)

And that should give me only the first 16 bytes correct? But if I have a temp file, then I'll need to unlink it, which seems a bit too complicated computationally for something so simple.

Anyways, any word on the content:// URI's causing this crash?

chris-pikul avatar Mar 26 '17 20:03 chris-pikul

About the content:// URI's problem, after some investigations I got some clues. In short, we have to handle this kind of URI in a different way, will update the status once it's complete.

wkh237 avatar Mar 27 '17 03:03 wkh237

I've added additional URI handling to fs.readFile and fs.readStream, please try to install the package from branch `issue-287.'

$ npm install --save git://github.com/wkh237/react-native-fetch-blob.git#issue-287

wkh237 avatar Mar 28 '17 02:03 wkh237

@tlvince I am having the same issue, with the same image picker. How did you do it in the end? Is this the line you updated? fs.readFile(uri, 'base64') Thanks

etiennewaldron avatar Apr 02 '17 23:04 etiennewaldron

@wkh237 Just tried it, it doesn't seem to fix my issue. Below is the URI I am using in fs.readFile: content://com.app.provider/app_images/Android/data/com.app/files/Pictures/image-2cf9181c-ab81-4fca-8241-fad4ed060156.jpg. Any ideas?

etiennewaldron avatar Apr 05 '17 09:04 etiennewaldron

@etiennewaldron , thanks for the feedback. Will look into the issue and find another possible solution.

wkh237 avatar Apr 05 '17 13:04 wkh237

Hi, do you have any news on this issue? Is there a quick fix I can use in the meantime? Thanks

etiennewaldron avatar Apr 14 '17 08:04 etiennewaldron

@etiennewaldron , I've just updated branch issue-287, I can read a picture from react-native-image-picker which has URI like this

content://com.rnfetchblobtest.provider/app_images/Pictures/image-c6f94579-a189-44da-9060-3fc9c613f354.jpg

Please try if that works, thanks 👍

wkh237 avatar Apr 16 '17 08:04 wkh237

Thank you for the quick response. Tested on Nexus 5X @ 6.0.0 and it's working great! No more app crash for me, everything is working as expected. Thanks again!

etiennewaldron avatar Apr 17 '17 13:04 etiennewaldron

I see a similar error when using File System Access API exists(path:string):Promise.

For example: RNFetchBlob.fs.exists('content://media/external/file/7853') // this is an existing file so this results in true RNFetchBlob.fs.exists('test') // this is an nonexistent path/file so this results in false RNFetchBlob.fs.exists('file://...') // true or false RNFetchBlob.fs.exists('content://media/external/file/7853xxxx') // this is an nonexistent file in an existing folder, but i get an app crash with "Exception in native call java.lang.NullPointerException at java.io.File.<init>(File.java:262)" on top of my stack

Could this be related?

skr1t avatar Apr 20 '17 09:04 skr1t

@skr1t , thanks for the reminder, will look into it 👍

wkh237 avatar Apr 20 '17 12:04 wkh237

I'm wondering if this is still closed though? If fs.exists doesn't think it's threre, then why would the 3rd party app supply the uri? As in the content://com.app.provider links that I was getting from Google Drive.

chris-pikul avatar May 01 '17 15:05 chris-pikul

Will this be merged/released soon? Thanks!

jamieparkinson avatar May 22 '17 11:05 jamieparkinson

@wkh237 @jamieparkinson sorry to resurrect this issue, but I am experiencing it myself despite pulling in the issue-287 branch, so I can't see how this is fixed unless I'm missing something. My issue is almost identical to @nordved's original report. Again, I am using ImagePicker as he was. The only slight difference is in the code I am working on, an image is being uploaded as follows:

const result = RNFetchBlob.fetch( 'PUT', url, headers, RNFetchBlob.wrap(uriFromImagePicker))

This throws the following warnings: RNFetchBlob failed to create single content request body :column '_data' does not exist and ReactNativeJS: Attempt to invoke virtual method 'int java.io.InputStream.read(byte[], int, int)' on a null object reference

This is the dependency in my package.json https://github.com/wkh237/react-native-fetch-blob#issue-287. Am I missing something obvious? I should add that this was working previously but I'm afraid I'm not sure exactly what the breaking change was. I guessing possibly the uri structure returned by ImagePicker.

Many thanks,

Miles

milesnash avatar Jun 06 '17 18:06 milesnash

I'm seeing the same problem when copying content uri produced by react-native-image-picker. This line RNFetchBlob.fs.cp(origin, destination) Where origin looks like this: content://com.app.provider/app_images/Android/data/com.app/files/Pictures/image-5c38441e-04c7-4497-a28a-24eebb4ac051.jpg Throws the following error: Error: Attempt to invoke virtual method 'boolean java.lang.String.startsWith(java.lang.String)' on a null object reference

I'm using the issue-287 branch as dependency (git://github.com/wkh237/react-native-fetch-blob.git#issue-287).

janiilmari avatar Jun 08 '17 13:06 janiilmari

Also having this problem, but the issue-287 branch seems to be working well for me. It's currently 63 commits behind master though. Wondering if you plan on merging this into master? If not, can you bring the branch up-to-date?

kashav avatar Jun 29 '17 03:06 kashav

@kshvmdn , thanks for the heads up. I fact I was thought the PR #374 is doing the same thing and it has been merged in 0.10.6 have you tried it yet ? If that does not fix the problem, perhaps we will need to merge this one as well.

wkh237 avatar Jun 29 '17 10:06 wkh237

not working on 0.10.6, and issue-287 gives me stat error: failed to list path " + path + " for it is not exist or it is not a folder

path == content://com.app.provider/app_images/Android/data/com.app/files/Pictures/image-7402dd55-4003-4094-a53c-69c852d27876.jpg

zkrige avatar Jun 29 '17 13:06 zkrige

Just updated branch issue-287, it's working on my end now. Please update your package from the branch, thanks 👍

wkh237 avatar Jul 02 '17 15:07 wkh237