diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index 3aad655aa..e81d5a374 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -1 +1,3 @@ -Hi ! Thank you for reporting an issue, but we would like to remind you, we have a trouble shooting page in our wiki. You may need to take a look on that page, perhaps the answer is just right there :p +Hi ! Thank you for reporting an issue, but we would like to remind you, we have a trouble shooting page in our wiki. You may want to take a look on that page :p + +* issues which have been tagged as 'needs feedback', will be closed after 2 weeks if receive no feedbacks. diff --git a/README.md b/README.md index 4ea5a1880..52839582a 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,38 @@ -# react-native-fetch-blob [![release](https://img.shields.io/github/release/wkh237/react-native-fetch-blob.svg?maxAge=86400&style=flat-square)](https://www.npmjs.com/package/react-native-fetch-blob) [![npm](https://img.shields.io/npm/v/react-native-fetch-blob.svg?style=flat-square)](https://www.npmjs.com/package/react-native-fetch-blob) ![](https://img.shields.io/badge/PR-Welcome-brightgreen.svg?style=flat-square) [![npm](https://img.shields.io/npm/l/express.svg?maxAge=2592000&style=flat-square)]() [![npm](https://img.shields.io/badge/inProgress-0.7.0-yellow.svg?style=flat-square)](https://github.com/wkh237/react-native-fetch-blob/milestones) +# react-native-fetch-blob [![release](https://img.shields.io/github/release/wkh237/react-native-fetch-blob.svg?maxAge=86400&style=flat-square)](https://www.npmjs.com/package/react-native-fetch-blob) [![npm](https://img.shields.io/npm/v/react-native-fetch-blob.svg?style=flat-square)](https://www.npmjs.com/package/react-native-fetch-blob) ![](https://img.shields.io/badge/PR-Welcome-brightgreen.svg?style=flat-square) [![npm](https://img.shields.io/npm/l/express.svg?maxAge=2592000&style=flat-square)]() -A module provides upload, download, and files access API. Supports file stream read/write for process large files. - -**Rationale** - -React Native does not support `Blob` object at this moment, which means if you're going to send/receive binary data via `fetch` API, that might not work as you expect. See [facebook/react-native#854](https://github.com/facebook/react-native/issues/854). - -For some use cases, you might get into trouble. For example, displaying an image that requires a specific field in headers (ex. "Authorization : Bearer ...") or body, so you can't just pass the image uri to `Image` component because that will probably returns a 401 response. Or you're going to upload binary data which generated from JS, the server will get an empry body due to [this issue](https://github.com/facebook/react-native/issues/854). With help of APIs provided by this module, you can send HTTP request with any headers, and decide how to handle the response/reqeust data without worry about if it is not supported by `fetch` API. The response data can be just simply converted into BASE64 string, or stored to a file directly so that you can read it by using file access APIs such as readFile, readStream. - -This module was designed to be a substitution of `Blob`, there's a set of APIs including basic file system CRUD method, and file stream reader/writer. Also it has a special `fetch` implementation that supports binary request/response body. - -**Backward Compatible** - -All updates are `backward-compatible` generally you don't have to change existing code unless you're going to use new APIs. But we recommend pre `0.5.0` users consider upgrade the package to latest version, since we have introduced new APIs can either `upload` or `download` files simply using a file path. It's much more memory efficent in some use case. We've also introduced `fs` APIs for access files, and `file stream` API that helps you read/write files (especially for **large ones**), see [Examples](#user-content-recipes) bellow. This module implements native methods, supports both Android (uses awesome native library [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client])) and IOS. +A project committed to make file acess and transfer easier and effiecient for React Native developers. ## TOC - +* [About](#user-content-about) +* [Backward Compatible](#user-content-backward-compatible) * [Installation](#user-content-installation) * [Recipes](#user-content-recipes) * [Download file](#user-content-download-example--fetch-files-that-needs-authorization-token) * [Upload file](#user-content-upload-example--dropbox-files-upload-api) * [Multipart/form upload](#user-content-multipartform-data-example--post-form-data-with-file-and-data) * [Upload/Download progress](#user-content-uploaddownload-progress) + * [Cancel HTTP request](#user-content-cancel-request) * [Android Media Scanner, and Download Manager Support](#user-content-android-media-scanner-and-download-manager-support) * [File access](#user-content-file-access) * [File stream](#user-content-file-stream) * [Manage cached files](#user-content-cache-file-management) * [Self-Signed SSL Server](#user-content-self-signed-ssl-server) * [API References](https://github.com/wkh237/react-native-fetch-blob/wiki/Fetch-API) +* [Trouble Shooting](https://github.com/wkh237/react-native-fetch-blob/wiki/Trouble-Shooting) * [Development](#user-content-development) +## About + +React Native does not support `Blob` object at this moment, which means if you're going to send/receive binary data via `fetch` API, that might not work as you expect. See [facebook/react-native#854](https://github.com/facebook/react-native/issues/854). + +For some use cases, you might get into trouble. For example, displaying an image that requires a specific field in headers (ex. "Authorization : Bearer ...") or body, so you can't just pass the image uri to `Image` component because that will probably returns a 401 response. Or you're going to upload binary data which generated from JS, the server will get an empry body due to [this issue](https://github.com/facebook/react-native/issues/854). With help of APIs provided by this module, you can send HTTP request with any headers, and decide how to handle the response/reqeust data without worry about if it is not supported by `fetch` API. The response data can be just simply converted into BASE64 string, or stored to a file directly so that you can read it by using file access APIs such as readFile, readStream. + +This module was designed to be a substitution of `Blob`, there's a set of APIs including basic file system CRUD method, and file stream reader/writer. Also it has a special `fetch` implementation that supports binary request/response body. + +## Backward Compatible + +All updates are `backward-compatible` generally you don't have to change existing code unless you're going to use new APIs. But we recommend pre `0.5.0` users consider upgrade the package to latest version, since we have introduced new APIs can either `upload` or `download` files simply using a file path. It's much more memory efficent in some use case. We've also introduced `fs` APIs for access files, and `file stream` API that helps you read/write files (especially for **large ones**), see [Examples](#user-content-recipes) bellow. This module implements native methods, supports both Android (uses same native library as offical RN fetch API [OkHttp](https://github.com/square/okhttp)) and IOS. + ## Installation Install package from npm @@ -44,9 +47,17 @@ Link package using [rnpm](https://github.com/rnpm/rnpm) rnpm link ``` -### For React Native >= 0.29.0 (Android) +### Manually link package + +If rnpm link command failed to link the package automatically, you might try manually link the package. + +Edit add package to`android/settings.gradle` -> If you're using react-native >= `0.29.0`, the package might not be able to link through `rnpm link`, and you might see an error screen similar to [#51](https://github.com/wkh237/react-native-fetch-blob/issues/51), this is because a [a bug in 0.29.0](https://github.com/facebook/react-native/commit/4dabb575b1b311ba541fae7eabbd49f08b5391b3), someone has already fixed it, but the solution does not work on our project, you may have to manually add the package yourself. +```diff +include ':app' ++ include ':react-native-fetch-blob' ++ project(':react-native-fetch-blob').projectDir = new File(rootProject.projectDir,' ../node_modules/react-native-fetch-blob/android') +``` Add this code to `MainApplication.java` @@ -63,6 +74,7 @@ protected List getPackages() { }; ... ``` +> If you still having problem on installing this package, please check the [trouble shooting page](https://github.com/wkh237/react-native-fetch-blob/wiki/Trouble-Shooting) or [file an issue](https://github.com/wkh237/react-native-fetch-blob/issues/new) **Grant Permission to External storage for Android 5.0 or lower** @@ -317,13 +329,18 @@ What if you want to upload a file in some field ? Just like [upload a file from #### Upload/Download progress -In `version >= 0.4.2` it is possible to know the upload/download progress. On Android, only download progress is supported. See [wiki](https://github.com/wkh237/react-native-fetch-blob/wiki/Fetch-API#fetchprogresseventlistenerpromisernfetchblobresponse) for more information. +In `version >= 0.4.2` it is possible to know the upload/download progress. After `0.7.0` IOS and Android upload progress are supported. ```js RNFetchBlob.fetch('POST', 'http://www.example.com/upload', { ... some headers, 'Content-Type' : 'octet-stream' }, base64DataString) + // listen to upload progress event + .uploadProgress((written, total) => { + console.log('uploaded', written / total) + }) + // listen to download progress event .progress((received, total) => { console.log('progress', received / total) }) @@ -335,6 +352,23 @@ In `version >= 0.4.2` it is possible to know the upload/download progress. On An }) ``` +#### Cancel Request + +After `0.7.0` it is possible to cancel a HTTP request. When the request cancel, it will definately throws an promise rejection, be sure to catch it. + +```js +let task = RNFetchBlob.fetch('GET', 'http://example.com/file/1') + +task.then(() => { ... }) + // handle request cancelled rejection + .catch((err) => { + console.log(err) + }) +// cancel the request, the callback function is optional +task.cancel((err) => { ... }) + +``` + #### Android Media Scanner, and Download Manager Support If you want to make a file in `External Storage` becomes visible in Picture, Downloads, or other built-in apps, you will have to use `Media Scanner` or `Download Manager`. @@ -569,6 +603,8 @@ RNFetchBlob.config({ | Version | | |---|---| +| 0.7.1 | Fix #57 ios module could not compile on ios version <= 9.3 | +| 0.7.0 | Add support of Android upload progress, and remove AsyncHttpClient dependency from Android native implementation. | | 0.6.4 | Fix rnpm link script. | | 0.6.3 | Fix performance issue on IOS, increase max concurrent request limitation from 1. | | 0.6.2 | Add support of asset file and camera roll files, Support custom MIME type when sending multipart request, thanks @smartt | diff --git a/package.json b/package.json index 5eb454730..f80fe907c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fetchblob", - "version": "0.6.4", + "version": "0.7.1", "private": true, "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", diff --git a/src/README.md b/src/README.md index 615d85131..743a90153 100644 --- a/src/README.md +++ b/src/README.md @@ -1,37 +1,40 @@ -# react-native-fetch-blob [![npm](https://img.shields.io/npm/v/react-native-fetch-blob.svg?style=flat-square)](https://www.npmjs.com/package/react-native-fetch-blob) ![](https://img.shields.io/badge/PR-Welcome-brightgreen.svg?style=flat-square) [![npm](https://img.shields.io/npm/l/express.svg?maxAge=2592000&style=flat-square)]() [![npm](https://img.shields.io/badge/inProgress-0.7.0-yellow.svg?style=flat-square)](https://github.com/wkh237/react-native-fetch-blob/milestones) +# react-native-fetch-blob [![release](https://img.shields.io/github/release/wkh237/react-native-fetch-blob.svg?maxAge=86400&style=flat-square)](https://www.npmjs.com/package/react-native-fetch-blob) [![npm](https://img.shields.io/npm/v/react-native-fetch-blob.svg?style=flat-square)](https://www.npmjs.com/package/react-native-fetch-blob) ![](https://img.shields.io/badge/PR-Welcome-brightgreen.svg?style=flat-square) [![npm](https://img.shields.io/npm/l/express.svg?maxAge=2592000&style=flat-square)]() [![npm](https://img.shields.io/badge/inProgress-0.7.0-yellow.svg?style=flat-square)](https://github.com/wkh237/react-native-fetch-blob/milestones) A module provides upload, download, and files access API. Supports file stream read/write for process large files. ## [Please check our github for updated document](https://github.com/wkh237/react-native-fetch-blob) -**Why do we need this** - -React Native does not support `Blob` object at this moment, which means if you're going to send/receive binary data via `fetch` API, that might not work as you expect. See [facebook/react-native#854](https://github.com/facebook/react-native/issues/854). - -For some use cases, you might get into trouble. For example, displaying an image that requires a specific field in headers (ex. "Authorization : Bearer ...") or body, so you can't just pass the image uri to `Image` component because that will probably returns a 401 response. Or you're going to upload binary data which generated from JS, the server will get an empry body due to [this issue](https://github.com/facebook/react-native/issues/854). With help of APIs provided by this module, you can send HTTP request with any headers, and decide how to handle the response/reqeust data without worry about if it is not supported by `fetch` API. The response data can be just simply converted into BASE64 string, or stored to a file directly so that you can read it by using file access APIs such as readFile, readStream. - -This module was designed to be a substitution of `Blob`, there's a set of APIs including basic file system CRUD method, and file stream reader/writer. Also it has a special `fetch` implementation that supports binary request/response body. - -**Backward Compatible** - -All updates are `backward-compatible` generally you don't have to change existing code unless you're going to use new APIs. But we recommend pre `0.5.0` users consider upgrade the package to latest version, since we have introduced new APIs can either `upload` or `download` files simply using a file path. It's much more memory efficent in some use case. We've also introduced `fs` APIs for access files, and `file stream` API that helps you read/write files (especially for **large ones**), see [Examples](#user-content-recipes) bellow. This module implements native methods, supports both Android (uses awesome native library [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client])) and IOS. - ## TOC - +* [About](#user-content-about) +* [Backward Compatible](#user-content-backward-compatible) * [Installation](#user-content-installation) * [Recipes](#user-content-recipes) * [Download file](#user-content-download-example--fetch-files-that-needs-authorization-token) * [Upload file](#user-content-upload-example--dropbox-files-upload-api) * [Multipart/form upload](#user-content-multipartform-data-example--post-form-data-with-file-and-data) * [Upload/Download progress](#user-content-uploaddownload-progress) + * [Cancel HTTP request](#user-content-cancel-request) * [Android Media Scanner, and Download Manager Support](#user-content-android-media-scanner-and-download-manager-support) * [File access](#user-content-file-access) * [File stream](#user-content-file-stream) * [Manage cached files](#user-content-cache-file-management) * [Self-Signed SSL Server](#user-content-self-signed-ssl-server) * [API References](https://github.com/wkh237/react-native-fetch-blob/wiki/Fetch-API) +* [Trouble Shooting](https://github.com/wkh237/react-native-fetch-blob/wiki/Trouble-Shooting) * [Development](#user-content-development) +## About + +React Native does not support `Blob` object at this moment, which means if you're going to send/receive binary data via `fetch` API, that might not work as you expect. See [facebook/react-native#854](https://github.com/facebook/react-native/issues/854). + +For some use cases, you might get into trouble. For example, displaying an image that requires a specific field in headers (ex. "Authorization : Bearer ...") or body, so you can't just pass the image uri to `Image` component because that will probably returns a 401 response. Or you're going to upload binary data which generated from JS, the server will get an empry body due to [this issue](https://github.com/facebook/react-native/issues/854). With help of APIs provided by this module, you can send HTTP request with any headers, and decide how to handle the response/reqeust data without worry about if it is not supported by `fetch` API. The response data can be just simply converted into BASE64 string, or stored to a file directly so that you can read it by using file access APIs such as readFile, readStream. + +This module was designed to be a substitution of `Blob`, there's a set of APIs including basic file system CRUD method, and file stream reader/writer. Also it has a special `fetch` implementation that supports binary request/response body. + +## Backward Compatible + +All updates are `backward-compatible` generally you don't have to change existing code unless you're going to use new APIs. But we recommend pre `0.5.0` users consider upgrade the package to latest version, since we have introduced new APIs can either `upload` or `download` files simply using a file path. It's much more memory efficent in some use case. We've also introduced `fs` APIs for access files, and `file stream` API that helps you read/write files (especially for **large ones**), see [Examples](#user-content-recipes) bellow. This module implements native methods, supports both Android (uses same native library as offical RN fetch API [OkHttp](https://github.com/square/okhttp)) and IOS. + ## Installation Install package from npm @@ -46,11 +49,32 @@ Link package using [rnpm](https://github.com/rnpm/rnpm) rnpm link ``` +### For React Native >= 0.29.0 (Android) + +> If you're using react-native >= `0.29.0`, the package might not be able to link through `rnpm link`, and you might see an error screen similar to [#51](https://github.com/wkh237/react-native-fetch-blob/issues/51), this is because a [a bug in 0.29.0](https://github.com/facebook/react-native/commit/4dabb575b1b311ba541fae7eabbd49f08b5391b3), someone has already fixed it, but the solution does not work on our project, you may have to manually add the package yourself. + +Add this code to `MainApplication.java` + +```diff +... ++ import com.RNFetchBlob.RNFetchBlobPackage; +... +protected List getPackages() { + return Arrays.asList( + new MainReactPackage(), ++ new RNFetchBlobPackage() + ); + } + }; +... +``` +> If you still having problem on installing this package, please check the [trouble shooting page](https://github.com/wkh237/react-native-fetch-blob/wiki/Trouble-Shooting) or [file an issue](https://github.com/wkh237/react-native-fetch-blob/issues/new) + **Grant Permission to External storage for Android 5.0 or lower** -Mechanism about granting Android permissions has slightly different since Android 6.0 released, please refer to [Officail Document](https://developer.android.com/training/permissions/requesting.html). +Mechanism about granting Android permissions has slightly different since Android 6.0 released, please refer to [Official Document](https://developer.android.com/training/permissions/requesting.html). -If you're going to access external storage (say, SD card storage) for `Android 5.0` (or lower) devices, you might have to add the following line to `AndroidManifetst.xml`. +If you're going to access external storage (say, SD card storage) for `Android 5.0` (or lower) devices, you might have to add the following line to `AndroidManifest.xml`. ```diff + imageView = }) ``` @@ -299,13 +323,18 @@ What if you want to upload a file in some field ? Just like [upload a file from #### Upload/Download progress -In `version >= 0.4.2` it is possible to know the upload/download progress. On Anroid, only download progress is supported. See [wiki](https://github.com/wkh237/react-native-fetch-blob/wiki/Fetch-API#fetchprogresseventlistenerpromisernfetchblobresponse) for more information. +In `version >= 0.4.2` it is possible to know the upload/download progress. After `0.7.0` IOS and Android upload progress are supported. ```js RNFetchBlob.fetch('POST', 'http://www.example.com/upload', { ... some headers, 'Content-Type' : 'octet-stream' }, base64DataString) + // listen to upload progress event + .uploadProgress((written, total) => { + console.log('uploaded', written / total) + }) + // listen to download progress event .progress((received, total) => { console.log('progress', received / total) }) @@ -317,6 +346,23 @@ In `version >= 0.4.2` it is possible to know the upload/download progress. On An }) ``` +#### Cancel Request + +After `0.7.0` it is possible to cancel a HTTP request. When the request cancel, it will definately throws an promise rejection, be sure to catch it. + +```js +let task = RNFetchBlob.fetch('GET', 'http://example.com/file/1') + +task.then(() => { ... }) + // handle request cancelled rejection + .catch((err) => { + console.log(err) + }) +// cancel the request, the callback function is optional +task.cancel((err) => { ... }) + +``` + #### Android Media Scanner, and Download Manager Support If you want to make a file in `External Storage` becomes visible in Picture, Downloads, or other built-in apps, you will have to use `Media Scanner` or `Download Manager`. @@ -403,7 +449,7 @@ RNFetchBlob.config({ File access APIs were made when developing `v0.5.0`, which helping us write tests, and was not planned to be a part of this module. However we realized that, it's hard to find a great solution to manage cached files, every one who use this moudle may need these APIs for there cases. -Before get started using file APIs we recommend read [Differences between File Source](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#differences-between-file-source) first. +Before start using file APIs, we recommend read [Differences between File Source](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#differences-between-file-source) first. File Access APIs - [asset (0.6.2)](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#assetfilenamestringstring) @@ -551,6 +597,10 @@ RNFetchBlob.config({ | Version | | |---|---| +| 0.7.1 | Fix #57 ios module could not compile on ios version <= 9.3 | +| 0.7.0 | Add support of Android upload progress, and remove AsyncHttpClient dependency from Android native implementation. | +| 0.6.4 | Fix rnpm link script. | +| 0.6.3 | Fix performance issue on IOS, increase max concurrent request limitation from 1. | | 0.6.2 | Add support of asset file and camera roll files, Support custom MIME type when sending multipart request, thanks @smartt | | 0.6.1 | Fix #37 progress report API issue on IOS | | 0.6.0 | Add readFile and writeFile API for easier file access, also added Android download manager support. | diff --git a/src/class/RNFetchBlobFile.js b/src/class/RNFetchBlobFile.js index d812743d6..51b9481da 100644 --- a/src/class/RNFetchBlobFile.js +++ b/src/class/RNFetchBlobFile.js @@ -1,3 +1,9 @@ +// Copyright 2016 wkh237@github. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. +// @flow + + import { NativeModules, DeviceEventEmitter, diff --git a/src/class/RNFetchBlobReadStream.js b/src/class/RNFetchBlobReadStream.js index b56712496..b54b82dc4 100644 --- a/src/class/RNFetchBlobReadStream.js +++ b/src/class/RNFetchBlobReadStream.js @@ -1,3 +1,8 @@ +// Copyright 2016 wkh237@github. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. +// @flow + import { NativeModules, DeviceEventEmitter, diff --git a/src/class/RNFetchBlobSession.js b/src/class/RNFetchBlobSession.js index c6fadc524..378df4097 100644 --- a/src/class/RNFetchBlobSession.js +++ b/src/class/RNFetchBlobSession.js @@ -1,7 +1,7 @@ -/** - * Session class - * @class RNFetchBlobSession - */ +// Copyright 2016 wkh237@github. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. +// @flow import { NativeModules, diff --git a/src/class/RNFetchBlobWriteStream.js b/src/class/RNFetchBlobWriteStream.js index 2483a0a2b..e10b229d2 100644 --- a/src/class/RNFetchBlobWriteStream.js +++ b/src/class/RNFetchBlobWriteStream.js @@ -1,3 +1,8 @@ +// Copyright 2016 wkh237@github. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. +// @flow + import { NativeModules, DeviceEventEmitter, diff --git a/src/fs.js b/src/fs.js index b72fa195e..34e5955f9 100644 --- a/src/fs.js +++ b/src/fs.js @@ -1,9 +1,7 @@ -/** - * @name react-native-fetch-blob-fs - * @author wkh237 - * @version 0.7.0 - * @flow - */ +// Copyright 2016 wkh237@github. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. +// @flow import { NativeModules, diff --git a/src/index.js b/src/index.js index 12ebaecce..73b41a41f 100644 --- a/src/index.js +++ b/src/index.js @@ -1,9 +1,7 @@ -/** - * @name react-native-fetch-blob - * @author wkh237 - * @version 0.7.0 - * @flow - */ +// Copyright 2016 wkh237@github. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. +// @flow import { NativeModules, @@ -163,6 +161,8 @@ function fetch(...args:any):Promise { } promise.cancel = (fn) => { fn = fn || function(){} + subscription.remove() + subscriptionUpload.remove() RNFetchBlob.cancelRequest(taskId, fn) } @@ -202,7 +202,7 @@ class FetchBlobResponse { */ this.blob = (contentType:string, sliceSize:number) => { console.warn('FetchBlobResponse.blob() is deprecated and has no funtionality.') - return null + return this } /** * Convert result to text. diff --git a/src/package.json b/src/package.json index dde70e26e..6ca4f03a5 100644 --- a/src/package.json +++ b/src/package.json @@ -1,6 +1,6 @@ { "name": "react-native-fetch-blob", - "version": "0.6.4", + "version": "0.7.1", "description": "A module provides upload, download, and files access API. Supports file stream read/write for process large files.", "main": "index.js", "scripts": { diff --git a/src/polyfill/Blob.js b/src/polyfill/Blob.js index 33570b36b..bf56abede 100644 --- a/src/polyfill/Blob.js +++ b/src/polyfill/Blob.js @@ -1,9 +1,7 @@ -/** - * @author wkh237 - * @since 2016/07/18 - * @description - * Web API Blob object polyfill. - */ +// Copyright 2016 wkh237@github. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. + import fs from '../fs.js' import getUUID from '../utils/uuid' diff --git a/src/polyfill/EventTarget.js b/src/polyfill/EventTarget.js new file mode 100644 index 000000000..6d32ee771 --- /dev/null +++ b/src/polyfill/EventTarget.js @@ -0,0 +1,42 @@ +// Copyright 2016 wkh237@github. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. + +export default class EventTarget { + + listeners : any; + + constructor() { + this.listeners = {} + } + + addEventListener(type:string, cb : () => void) { + if(!(type in this.listeners)) { + this.listeners[type] = [] + } + this.listeners[type].push(cb) + } + + removeEventListener(type:string, cb:() => any) { + if(!(type in this.listeners)) + return + let handlers = this.listeners[type] + for(let i in handlers) { + if(cb === handlers[i]) { + handlers.splice(i,1) + return this.removeEventListener(type, cb) + } + } + } + + dispatchEvent(event:Event) { + if(!(event.type in this.listeners)) + return + let handlers = this.listeners[event.type] + for(let i in handlers) { + handlers[i].call(this, event) + } + + } + +} diff --git a/src/polyfill/File.js b/src/polyfill/File.js index a195940dc..18966e186 100644 --- a/src/polyfill/File.js +++ b/src/polyfill/File.js @@ -1,9 +1,7 @@ -/** - * @author wkh237 - * @since 2016/07/18 - * @description - * Web API File object polyfill. - */ +// Copyright 2016 wkh237@github. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. + import fs from '../fs.js' import Blob from './Blob.js' diff --git a/src/polyfill/XMLHttpRequest.js b/src/polyfill/XMLHttpRequest.js index a3bdeac2e..49ef4ced7 100644 --- a/src/polyfill/XMLHttpRequest.js +++ b/src/polyfill/XMLHttpRequest.js @@ -1,15 +1,175 @@ -export default class XMLHttpRequest { +// Copyright 2016 wkh237@github. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. - constructor(...args) { - console.log('XMLHttpRequest constructor called', args) +import RNFetchBlob from '../index.js' +import EventTarget from './EventTarget.js' + +export default class XMLHttpRequest extends EventTarget{ + + onreadystatechange : () => void; + onabort : () => void; + onerror : () => void; + onload : () => void; + onloadstart : () => void; + onprogress : () => void; + ontimeout : () => void; + onloadend : () => void; + + readyState : number; + response : any; + responseText : any; + responseType : '' | 'arraybuffer' | 'blob' | 'document' | 'json' | 'text'; + // TODO : not suppoted for now + responseURL : null; + responseXML : null; + status : number; + statusText : string; + timeout : number; + + // RNFetchBlob compatible data structure + _config : RNFetchBlobConfig; + _url : any; + _method : string; + _headers: any; + _body: any; + + // RNFetchBlob promise object, which has `progress`, `uploadProgress`, and + // `cancel` methods. + _task: any; + + constructor() { + super() + console.log('---------------------------------') + console.log('XMLHttpRequest constructor called') + this._config = {} + this._args = {} + this._headers = {} + this.readyState = 0 + this.response = null + this.responseText = null + } + + // XMLHttpRequest.open, always async, user and password not supported. + open(method:string, url:string, async:true, user:any, password:any) { + console.log('---------------------------------') + console.log('XMLHttpRequest open called', method, url, async, user, password) + this._method = method + this._url = url + this.readyState = 1 + if(this.onload) + this.onload() + if(this.onloadstart) + this.onloadstart() } - send(...data) { - console.log('XMLHttpRequest send called', data) + addEventListener(event, listener) { + console.log('---------------------------------') + console.log('XMLHttpRequest add listener', event, listener.toString()) + this.addEventListener(event, listener) + } + + /** + * Invoke this function to send HTTP request, and set body. + * @param {any} body Body in RNfetchblob flavor + */ + send(body) { + console.log('---------------------------------') + console.log('XMLHttpRequest send called', body) + let [_method, _url, _headers] = this + console.log('sending request with args', _method, _url, _headers, body) + + this._task = RNFetchBlob.fetch(_method, _url, _headers, body) + this._task + .uploadProgress(this._progressEvent) + .onProgress(this._progressEvent) + .then(this._onDone) + .catch(this._onError) + } + + overrideMimeType(mime:string) { + this.headers['content-type'] = mime + } + + setRequestHeader(name, value) { + console.log('XMLHttpRequest set header', name, value) + this._headers[name] = value + } + + abort() { + console.log('---------------------------------') + console.log('XMLHttpRequest abort called', this._task) + this._task.cancel((err) => { + let e = { + timeStamp : Date.now(), + } + if(this.onabort) + this.onabort() + if(!err) { + e.detail = err + e.type = 'error' + this.dispatchEvent('error', e) + } + else { + e.type = 'abort' + this.dispatchEvent('abort', e) + } + }) + } + + getResponseHeader(field:string):string | null{ + + } + + getAllResponseHeaders():string | null { + + } + + set onreadystatechange(handler:() => void) { + this.onreadystatechange = handler + } + + _progressEvent(send:number, total:number) { + let lengthComputable = false + if(total && total >= 0) + lengthComputable = true + else { + this.dispatchEvent('progress', + { loaded : send, total, lengthComputable }) + } + + if(this.onprogress) + this.onprogress({loaded : send, total, lengthComputable}) + } + + _onError(err) { + this.statusText = err + + if(String(err).match('timeout') !== null) { + if(this.ontimeout) + this.ontimeout() + } + else if(this.onerror) { + this.onerror({ + type : 'error', + detail : err + }) + } } - abort(...args) { - console.log('XMLHttpRequest abort called', data) + _onDone(resp) { + this.statusText = '200 OK' + switch(resp.type) { + case 'base64' : + this.responseType = 'text' + this.responseText = resp.text() + this.response = this.responseText + break; + case 'path' : + this.responseType = 'blob' + this.response = resp.blob() + break; + } } } diff --git a/src/scripts/prelink.js b/src/scripts/prelink.js index dc216574e..479ea9f79 100644 --- a/src/scripts/prelink.js +++ b/src/scripts/prelink.js @@ -13,15 +13,14 @@ var package = JSON.parse(fs.readFileSync(PACKAGE_JSON)); var APP_NAME = package.name; var APPLICATION_MAIN = process.cwd() + '/android/app/src/main/java/com/' + APP_NAME.toLocaleLowerCase() + '/MainApplication.java'; -if(!fs.existsSync(APPLICATION_MAIN)) { - throw 'RNFetchBlob could not found link Android automatically, MainApplication.java not found in path : ' + APPLICATION_MAIN -} - var VERSION = checkVersion(); console.log('RNFetchBlob detected app version .. ' + VERSION); if(VERSION >= 0.29) { console.log('RNFetchBlob patching MainApplication.java .. '); + if(!fs.existsSync(APPLICATION_MAIN)) { + throw 'RNFetchBlob could not link Android automatically, MainApplication.java not found in path : ' + APPLICATION_MAIN + } var main = fs.readFileSync(APPLICATION_MAIN); if(String(main).match('new RNFetchBlobPackage()') !== null) { console.log('skipped');