-
Notifications
You must be signed in to change notification settings - Fork 24.4k
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
Blobs #11103
Comments
Can you coordinate with @satya164, he has a Blob implementation almost ready I believe. |
Yep, that's the reason for this issue :), so that we can coordinate. I believe he's uplifting our Blob implementation. |
Hey! Yeah, so I've been working to port changes from @philikon's implementation to RN master. I've only worked on Android part so far. My focus was to first get it working with firebase so people could upload files to firebase. This has slightly different requirements since we need to create a blob locally from a file before uploading. So I think in addition to the proposed APIs, we need two more non-standard methods,
I just copied @philikon's implementation for the blob module and with minor changes, and writing some code to support XHR I've been able to get the following working,
I couldn't get I've not yet tested the WebSocket implementation yet, but since that was already implemented I guess shouldn't take much time to get it working. So things I need to do are,
What I'd like to explore is, right now when you create a blob from URI, I read it to memory as bytes. But we could probably just store the uri and read the bytes when needed (we'd need get the bytes length though, so we'd need to read it twice!) I also want to know if there's a full test suite available to test my implementation against. |
|
Libraries like firebase expect a blob or file object for uploading. We cannot pass a Firebase API looks like this, const ref = firebase.storage().ref().child('image.jpg');
const snapshot = await ref.put(blob);
This is so that we'll be able to pass blob objects to libraries which don't accept uris. I think in general this should be discouraged though, and libraries can internally use this API if they need. |
Meh ok. Seems unnecessary, unless there's demand from 3rd party libraries out there. (Perhaps Firebase?)
Ok, so then just do const response = await fetch(uri);
const blob = await response.blob();
someFirebaseAPI.consume(blob); Or in XHR spelling: const xhr = new XMLHttpRequest();
xhr.open('GET', uri);
xhr.responseType = 'blob';
xhr.onload = () => {
const blob = xhr.response;
someFirebaseAPI.consume(blob);
};
xhr.send(); Either variant will load the data from the URI into a |
It's very tiny amount code to polyfill a web API, which makes sure libs which need File constructor will work.
I didn't know I can do fetch from local URI. Or are you proposing to implement this API?
Yes |
Yep, should already work! (* Definitely on iOS. No idea about Android. If XHR can't currently download from |
Sure, ok. |
I had the same thought, the issue that @satya164 pointed out to me is that if the datasource API (let's say ImagePicker which lets you pick an image from your camera roll or take a photo) returns a Blob every time then people who are not interested in the Blob but rather in other other values like the URI might just forget to close the Blob. We could make it an optional parameter on those APIs: let imageBlob = ImagePicker.launchImageLibraryAsync({
allowsEditing: false,
aspect: [1, 2],
responseType: 'blob',
}) (the ImagePicker I refer to here is the one in Exponent - see docs if you're curious) |
Another approach would be to write a separate module that creates a Blob from a URI -- That said, one thing I like about libraries that return Blobs (like Brent's ImagePicker example) is that you either get back a valid Blob (assuming it's eagerly loaded) or the call fails. There's no uncertain state halfway where you get back a valid URI but then the file on disk gets deleted before you load the Blob from the URI. So we might want both -- Blob-aware APIs that give you back Blobs in a more atomic way, and a generic URI-to-Blob loader that works with any URI-aware API. |
Separate module for creating blobs from URI sounds good to me
That could work, it only saves one line of code of code though (not really since you've to specify While the blob-aware APIs seem nice to me in a general sense, in case of RN I'm not super happy about them since the user always has to manually free the blob. . One thing I wanted to explore is to lazy-load URI based blobs. But this negates the case @ide mentioned about not having to deal with uncertain state. |
Closing this issue because it has been inactive for a while. If you think it should still be opened let us know why. |
Summary: This is the first PR from a series of PRs grabbou and me will make to add blob support to React Native. The next PR will include blob support for XMLHttpRequest. I'd like to get this merged with minimal changes to preserve the attribution. My next PR can contain bigger changes. Blobs are used to transfer binary data between server and client. Currently React Native lacks a way to deal with binary data. The only thing that comes close is uploading files through a URI. Current workarounds to transfer binary data includes encoding and decoding them to base64 and and transferring them as string, which is not ideal, since it increases the payload size and the whole payload needs to be sent via the bridge every time changes are made. The PR adds a way to deal with blobs via a new native module. The blob is constructed on the native side and the data never needs to pass through the bridge. Currently the only way to create a blob is to receive a blob from the server via websocket. The PR is largely a direct port of https://github.com/silklabs/silk/tree/master/react-native-blobs by philikon into RN (with changes to integrate with RN), and attributed as such. > **Note:** This is a breaking change for all people running iOS without CocoaPods. You will have to manually add `RCTBlob.xcodeproj` to your `Libraries` and then, add it to Build Phases. Just follow the process of manual linking. We'll also need to document this process in the release notes. Related discussion - #11103 - `Image` can't show image when `URL.createObjectURL` is used with large images on Android The websocket integration can be tested via a simple server, ```js const fs = require('fs'); const http = require('http'); const WebSocketServer = require('ws').Server; const wss = new WebSocketServer({ server: http.createServer().listen(7232), }); wss.on('connection', (ws) => { ws.on('message', (d) => { console.log(d); }); ws.send(fs.readFileSync('./some-file')); }); ``` Then on the client, ```js var ws = new WebSocket('ws://localhost:7232'); ws.binaryType = 'blob'; ws.onerror = (error) => { console.error(error); }; ws.onmessage = (e) => { console.log(e.data); ws.send(e.data); }; ``` cc brentvatne ide Closes #11417 Reviewed By: sahrens Differential Revision: D5188484 Pulled By: javache fbshipit-source-id: 6afcbc4d19aa7a27b0dc9d52701ba400e7d7e98f
Summary: This is the first PR from a series of PRs grabbou and me will make to add blob support to React Native. The next PR will include blob support for XMLHttpRequest. I'd like to get this merged with minimal changes to preserve the attribution. My next PR can contain bigger changes. Blobs are used to transfer binary data between server and client. Currently React Native lacks a way to deal with binary data. The only thing that comes close is uploading files through a URI. Current workarounds to transfer binary data includes encoding and decoding them to base64 and and transferring them as string, which is not ideal, since it increases the payload size and the whole payload needs to be sent via the bridge every time changes are made. The PR adds a way to deal with blobs via a new native module. The blob is constructed on the native side and the data never needs to pass through the bridge. Currently the only way to create a blob is to receive a blob from the server via websocket. The PR is largely a direct port of https://github.com/silklabs/silk/tree/master/react-native-blobs by philikon into RN (with changes to integrate with RN), and attributed as such. > **Note:** This is a breaking change for all people running iOS without CocoaPods. You will have to manually add `RCTBlob.xcodeproj` to your `Libraries` and then, add it to Build Phases. Just follow the process of manual linking. We'll also need to document this process in the release notes. Related discussion - facebook/react-native#11103 - `Image` can't show image when `URL.createObjectURL` is used with large images on Android The websocket integration can be tested via a simple server, ```js const fs = require('fs'); const http = require('http'); const WebSocketServer = require('ws').Server; const wss = new WebSocketServer({ server: http.createServer().listen(7232), }); wss.on('connection', (ws) => { ws.on('message', (d) => { console.log(d); }); ws.send(fs.readFileSync('./some-file')); }); ``` Then on the client, ```js var ws = new WebSocket('ws://localhost:7232'); ws.binaryType = 'blob'; ws.onerror = (error) => { console.error(error); }; ws.onmessage = (e) => { console.log(e.data); ws.send(e.data); }; ``` cc brentvatne ide Closes facebook/react-native#11417 Reviewed By: sahrens Differential Revision: D5188484 Pulled By: javache fbshipit-source-id: 6afcbc4d19aa7a27b0dc9d52701ba400e7d7e98f
@hramos Please reopen , blob support is very critical to my current issue. #16034 (comment) |
Theres no point in re-opening. There's already a WIP PR implementing it. |
Can you post that here and on the ticket I've opened? ETA on completion etc.? |
There's no ETA. #11573 |
So how can we get this issue prioritized, it appears that PR has been in limbo for almost a year |
Only way is to help me with the iOS code and then wait for review. |
@satya164 What is needed on IOS side? |
@satya164 could you share me with Andriod code? Binary data communication API between JSC and Native using RN bridge is very important. I am the only concern for Andriod. |
@pradeep250677 you can check the pr linked above. |
Here at Silk Labs we've had a Blob implementation for React Native for a while. We want to contribute it back upstream. This issue discusses the API and implementation and tracks progress.
Motivation
Like in the browser, Blobs are opaque lumps of (usually binary) data that can be read into TypedArrays or strings, but don't have to be. Concretely in React Native that means that the binary data lives in native and not in JS, unless you explicitly request it. Why is this useful? Say you're receiving some data via XHR, WebSocket, or WebRTC, or some custom method that you've implemented and you want to display it in an
<Image>
view. Or you want to send it along through some other means without looking paying the cost of transferring it to the JS thread and back.We already have something somewhat similar to this for images on iOS (RCTImageStoreManager). This would be a generalization of that.
API
The web has an API for Blobs. It's not particularly pretty or anything, but it's kind of a standard, so I think we should use that, or at least a pretty good subset.
Creating
Blobs typically get created when JS is receiving data, e.g. via XHR, WebSocket, etc. I am planning on making
and
work so that when you specify those settings, the XHR and WebSocket responses will return Blob objects and not transfer the data to the JS thread. This works exactly like on the web.
Mutating
A subset of mutation operations will be supported:
I'm not planning on supporting creating a blob in JS from JS data (e.g. a string or TypedArray), though it should be easily implementable.
Consuming
Like in the browser, you'll be able to map Blobs to URIs that you can then use in things that eat URIs, e.g. the view:
Also like in the browser, you'll be able to read the blob into a TypedArray or string. I am planning on simply implementing the web's FileReader API.
Freeing
The following method is part of the Blob standard, but is currently not implemented by browsers. However, because we can't automatically garbage collect our blobs like browsers can, it will be necessary to provide a manual way of freeing blobs, so that consumers can make use of it when appropriate:
Here's a complete example of how consuming blobs would work: https://gist.github.com/philikon/4592efd153673f3e64dec353046af7a8
Implementation
Proposal
React Native already has a loose concept of a "blob", in other words, a lump of data that's not directly accessible by JS. The iOS (RCTImageStoreManager) mentioned above is an example.
XHR and most notably the
<Image>
tag already have a way to express a reference to a blob:How does
some://uri/that/gets/resolved
get resolved? On iOS, it gets resolved through aRCTURLRequestHandler
. On Android, it gets resolved through aContentProvider
.For instance, you can upload binary data provided by a system resource in the following way:
As long as
some://big/blob/of/binary/data
is resolvable by aRCTURLRequestHandler
orContentProvider
, this will Just Work(tm) already.On this basis, I'm proposing to implement Blobs as simply another way of URI-addressable binary data. Our implementation does exactly that.
Progress
Prep work:
Make XMLHttpRequest and XMLHttpRequest.upload proper EventTargets #7017)Add responseType as a concept to RCTNetworking, send binary data as base64 #8324)Implementation work, most likely by porting silk-react-native-blobs:
Blob
classRCTURLRequestHandler
on iOS,ContentProvider
on Android)Future implementation work:
xhr.responseType = 'blob'
andxhr.send(blob)
websocket.binaryType = 'blob'
andwebsocket.send(blob)
The text was updated successfully, but these errors were encountered: