[fetch] Does fetch with blob() marshal data across the bridge? #854

Closed
joewood opened this Issue Apr 15, 2015 · 20 comments

Projects

None yet
@joewood
joewood commented Apr 15, 2015

When you use .blob() on the response from fetch, is the data actually marshaled across the bridge? Or is the blob a handle on the data on the native side?

@joewood
joewood commented Apr 18, 2015

I'm trying to work through the best way of handling a lot of binary data. The best approach is to leave the binary data on the native side. Is the strategy here to use a tag, like how the camera roll refers to? Can fetch be set-up to return a 'blob tag' - equivalent to an 'image tag'?

@brentvatne brentvatne changed the title from Does fetch with blob() marshal data across the bridge? to [fetch] Does fetch with blob() marshal data across the bridge? May 31, 2015
@ghost
ghost commented Aug 4, 2015

Thank you for reporting this issue and appreciate your patience. We've notified the core team for an update on this issue. We're looking for a response within the next 30 days or the issue may be closed.

@nicklockwood
Contributor

@joewood this is exactly what I've been considering - storing data on the native side and sending a tag to the JS as the XHR response.

The problem with this approach is controlling the lifecycle of the data. We'd have no way of knowing if JS discarded the tag, so we wouldn't know when to release the data on the native side. We could put it in a LRU cache, but then you have the opposite problem, where the data has been released but you're still holding on to the tag, expecting it to work next time you use it.

I'm open to suggestions.

One option would be to encode enough info in the tag that it can re-download the data again if it's been discarded from the cache. I'm not sure if that would work in practice though.

Another option I've considered is that rather than downloading data to RAM, the "tag" will be a local file URL, and we'll provide a file manager so that the caller can then move or delete that file manually, otherwise it will remain indefinitely.

@nsainaney

In my case the blob is an image that I need to get to <Image source={...} />. No suggestions but just reporting a use case.

@ssomnoremac

@nicklockwood: curious if there's any progress on this. In my case I need to post the blob after a fetch. Seems like a common use case.

@nicklockwood
Contributor

@ssomnoremac we haven't attempted to solve the problem of marshalling arbitrary binary data across the bridge yet, but we support adding file attachments to XHR requests by just specifying the url so that the data never needs to cross the bridge (it will download and upload the data on the native side as a single action).

Alternatively, if it's an image, there's a workaround involving using the ImageStore module to export the image to JS as a base64 string.

@nicklockwood
Contributor

@nsainaney I'm a bit unclear on your use case. If you have a url that returns a blob of imageData, can't you pass the url as the <Image> source directly?

@ssomnoremac

@nicklockwood: Brilliant, prefer the first option. Second works but increases the payload size. Not sure I follow "specifying the url", I have two urls in my case: a remote and a local (couchbase-lite) device database. is it in fetch docs?

@nicklockwood
Contributor

@ssomnoremac I've only tried it with plain XHR, but I assume it works with fetch as well.

The trick is to use our FormData polyfill. It seems like the docs for that aren't on the website, but it's pretty well-documented in the FormData.js file:

https://github.com/facebook/react-native/blob/master/Libraries/Network/FormData.js

@ssomnoremac

Great Nick, this looks great. Could be a life saver for our app. Thanks so
much!
On Mar 3, 2016 6:38 PM, "Nick Lockwood" notifications@github.com wrote:

@ssomnoremac https://github.com/ssomnoremac I've only tried it with
plain XHR, but I assume it works with fetch as well.

The trick is to use our FormData polyfill. It seems like the docs for that
aren't on the website, but it's pretty well-documented in the FormData.js
file:

https://github.com/facebook/react-native/blob/master/Libraries/Network/FormData.js


Reply to this email directly or view it on GitHub
#854 (comment)
.

@nicklockwood
Contributor

cc: @mkonicek, @bestander - can we get the FormData docs added to the web site? It's not the first time this has come up, and judging by the number of 3rd party file upload modules, I don't think anyone knows this feature exists.

@mkonicek
Contributor
mkonicek commented Mar 4, 2016

@joewood Thanks for flagging this! Would you be up for sending a PR to update the docs?

@experimentsin

@nicklockwood One use case we have where it seems passing a URL to <Image> can't help is when the remote image in question is secured and requires a custom access token header to be passed as part of the request. In that case it looks like we need to make a full strength fetch or XHR request to access the data then somehow hand it off locally in such a way that <Image> can address it.

@nicklockwood
Contributor

@experimentsin ah, good point. We should extend the image source object to include headers and http method, like the one for webview.

We'd need to do some work on RCTImageLoader as well to make it accept NSURLRequests and not just url strings.

@lu-ko
lu-ko commented Mar 11, 2016

@experimentsin +1 It's exactly my case. I'm looking forward for some solution that could be simply used.

@nsainaney

@nicklockwood, @experimentsin got it. The image server I'm dealing with requires an auth token in the header.

@bestander
Contributor

The problem with this approach is controlling the lifecycle of the data. We'd have no way of knowing if JS discarded the tag, so we wouldn't know when to release the data on the native side. We could put it in a LRU cache, but then you have the opposite problem, where the data has been released but you're still holding on to the tag, expecting it to work next time you use it.

I'm open to suggestions.

@nicklockwood in browsers this problem is solved with URL.createObjectURL().
Developers are supposed to call URL.revokeObjectURL() manually when the binary data in the native memory is no more needed.
It is logical to repeat the same approach in RN.

@ssomnoremac ssomnoremac referenced this issue in couchbaselabs/react-native-couchbase-lite Apr 27, 2016
Closed

Images in Example project as Couchbase Lite attachments #11

@wkh237
wkh237 commented May 10, 2016

Hi, I also got the problem when upload/download blob data, so I made a RN native module so that I can upload/download blob data then process it in JS context.

Is there any progress on this issue? or there's any way to do this without writing native code?

@lacker
Contributor
lacker commented Oct 21, 2016

This issue is asking a question which seems to be answered, so I'm going to close it. I think it's okay if the best answers are libraries like react-native-fetch-blob, for what it's worth - we don't need to solve every single thing inside the core library.

@lacker lacker closed this Oct 21, 2016
@nicklockwood nicklockwood was unassigned by lacker Oct 21, 2016
@brentvatne
Member

@lacker - revision on that comment: #11103

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment