react-native/Libraries/Blob/FileReader.js

155 lines
3.1 KiB
JavaScript
Raw Permalink Normal View History

Implement Blob support for XMLHttpRequest Summary: This PR is a followup to https://github.com/facebook/react-native/pull/11417 and should be merged after that one is merged. 1. Add support for creating blobs from strings, not just other blobs 1. Add the `File` constructor which is a superset of `Blob` 1. Add the `FileReader` API which can be used to read blobs as strings or data url (base64) 1. Add support for uploading and downloading blobs via `XMLHttpRequest` and `fetch` 1. Add ability to download local files on Android so you can do `fetch(uri).then(res => res.blob())` to get a blob for a local file (iOS already supported this) 1. Clone the repo https://github.com/expo/react-native-blob-test 1. Change the `package.json` and update `react-native` dependency to point to this branch, then run `npm install` 1. Run the `server.js` file with `node server.js` 1. Open the `index.common.js` file and replace `localhost` with your computer's IP address 1. Start the packager with `yarn start` and run the app on your device If everything went well, all tests should pass, and you should see a screen like this: ![screen shot 2017-06-08 at 7 53 08 pm](https://user-images.githubusercontent.com/1174278/26936407-435bbce2-4c8c-11e7-9ae3-eb104e46961e.png)! Pull to rerun all tests or tap on specific test to re-run it [GENERAL] [FEATURE] [Blob] - Implement blob support for XMLHttpRequest Closes https://github.com/facebook/react-native/pull/11573 Reviewed By: shergin Differential Revision: D6082054 Pulled By: hramos fbshipit-source-id: cc9c174fdefdfaf6e5d9fd7b300120a01a50e8c1
2018-01-26 17:06:14 +00:00
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
Implement Blob support for XMLHttpRequest Summary: This PR is a followup to https://github.com/facebook/react-native/pull/11417 and should be merged after that one is merged. 1. Add support for creating blobs from strings, not just other blobs 1. Add the `File` constructor which is a superset of `Blob` 1. Add the `FileReader` API which can be used to read blobs as strings or data url (base64) 1. Add support for uploading and downloading blobs via `XMLHttpRequest` and `fetch` 1. Add ability to download local files on Android so you can do `fetch(uri).then(res => res.blob())` to get a blob for a local file (iOS already supported this) 1. Clone the repo https://github.com/expo/react-native-blob-test 1. Change the `package.json` and update `react-native` dependency to point to this branch, then run `npm install` 1. Run the `server.js` file with `node server.js` 1. Open the `index.common.js` file and replace `localhost` with your computer's IP address 1. Start the packager with `yarn start` and run the app on your device If everything went well, all tests should pass, and you should see a screen like this: ![screen shot 2017-06-08 at 7 53 08 pm](https://user-images.githubusercontent.com/1174278/26936407-435bbce2-4c8c-11e7-9ae3-eb104e46961e.png)! Pull to rerun all tests or tap on specific test to re-run it [GENERAL] [FEATURE] [Blob] - Implement blob support for XMLHttpRequest Closes https://github.com/facebook/react-native/pull/11573 Reviewed By: shergin Differential Revision: D6082054 Pulled By: hramos fbshipit-source-id: cc9c174fdefdfaf6e5d9fd7b300120a01a50e8c1
2018-01-26 17:06:14 +00:00
*
* @providesModule FileReader
* @flow
* @format
*/
'use strict';
const EventTarget = require('event-target-shim');
const Blob = require('Blob');
const {FileReaderModule} = require('NativeModules');
type ReadyState =
| 0 // EMPTY
| 1 // LOADING
| 2; // DONE
type ReaderResult = string | ArrayBuffer;
const READER_EVENTS = [
'abort',
'error',
'load',
'loadstart',
'loadend',
'progress',
];
const EMPTY = 0;
const LOADING = 1;
const DONE = 2;
class FileReader extends EventTarget(...READER_EVENTS) {
static EMPTY = EMPTY;
static LOADING = LOADING;
static DONE = DONE;
EMPTY = EMPTY;
LOADING = LOADING;
DONE = DONE;
_readyState: ReadyState;
_error: ?Error;
_result: ?ReaderResult;
_aborted: boolean = false;
_subscriptions: Array<*> = [];
constructor() {
super();
this._reset();
}
_reset(): void {
this._readyState = EMPTY;
this._error = null;
this._result = null;
}
_clearSubscriptions(): void {
this._subscriptions.forEach(sub => sub.remove());
this._subscriptions = [];
}
_setReadyState(newState: ReadyState) {
this._readyState = newState;
this.dispatchEvent({type: 'readystatechange'});
if (newState === DONE) {
if (this._aborted) {
this.dispatchEvent({type: 'abort'});
} else if (this._error) {
this.dispatchEvent({type: 'error'});
} else {
this.dispatchEvent({type: 'load'});
}
this.dispatchEvent({type: 'loadend'});
}
}
readAsArrayBuffer() {
throw new Error('FileReader.readAsArrayBuffer is not implemented');
}
readAsDataURL(blob: Blob) {
this._aborted = false;
FileReaderModule.readAsDataURL(blob.data).then(
(text: string) => {
if (this._aborted) {
return;
}
this._result = text;
this._setReadyState(DONE);
},
error => {
if (this._aborted) {
return;
}
this._error = error;
this._setReadyState(DONE);
},
);
}
readAsText(blob: Blob, encoding: string = 'UTF-8') {
this._aborted = false;
FileReaderModule.readAsText(blob.data, encoding).then(
(text: string) => {
if (this._aborted) {
return;
}
this._result = text;
this._setReadyState(DONE);
},
error => {
if (this._aborted) {
return;
}
this._error = error;
this._setReadyState(DONE);
},
);
}
abort() {
this._aborted = true;
// only call onreadystatechange if there is something to abort, as per spec
if (this._readyState !== EMPTY && this._readyState !== DONE) {
this._reset();
this._setReadyState(DONE);
}
// Reset again after, in case modified in handler
this._reset();
}
get readyState(): ReadyState {
return this._readyState;
}
get error(): ?Error {
return this._error;
}
get result(): ?ReaderResult {
return this._result;
}
}
module.exports = FileReader;