facebook / react-native

A framework for building native applications using React

Home Page:https://reactnative.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

joewood opened this issue · comments

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?

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'?

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.

@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.

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

@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.

@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.

@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?

@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?

@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

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)
.

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.

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

@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.

@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.

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

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

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.

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?

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 - revision on that comment: #11103

There seems to be a trend of closing issues that are important for broader implications than simply fetching images and displaying them, data blob creation is important for many use cases and is used widely in many other JvaScript execution environments, please see my latest issue ticket @lacker #16034 (comment)