123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- /**
- * @author wkh237
- * @version 0.5.0
- * @flow
- */
-
- import {
- NativeModules,
- DeviceEventEmitter,
- NativeAppEventEmitter,
- Platform,
- } from 'react-native'
-
-
- type fetchConfig = {
- fileCache : bool,
- path : string,
- appendExt : string
- };
-
- type RNFetchBlobNative = {
- fetchBlob : (
- options:fetchConfig,
- taskId:string,
- method:string,
- url:string,
- headers:any,
- body:any,
- callback:(err:any, ...data:any) => void
- ) => void,
- fetchBlobForm : (
- options:fetchConfig,
- taskId:string,
- method:string,
- url:string,
- headers:any,
- form:Array<any>,
- callback:(err:any, ...data:any) => void
- ) => void,
- readStream : (
- path:string,
- encode: 'utf8' | 'ascii' | 'base64'
- ) => void,
- getEnvironmentDirs : (dirs:any) => void,
- flush : () => void
- };
-
- import base64 from 'base-64'
- const emitter = (Platform.OS === 'android' ? DeviceEventEmitter : NativeAppEventEmitter)
- const RNFetchBlob:RNFetchBlobNative = NativeModules.RNFetchBlob
-
- emitter.addListener("RNFetchBlobMessage", (e) => {
-
- if(e.event === 'warn') {
- console.warn(e.detail)
- }
- else if (e.event === 'error') {
- throw e.detail
- }
- else {
- console.log("RNFetchBlob native message", e.detail)
- }
-
- })
-
- // Show warning if native module not detected
- if(!RNFetchBlob || !RNFetchBlob.fetchBlobForm || !RNFetchBlob.fetchBlob) {
- console.warn(
- 'react-native-fetch-blob could not find valid native module.',
- 'please make sure you have linked native modules using `rnpm link`,',
- 'and restart RN packager or manually compile IOS/Android project.'
- )
- }
-
- function getSystemDirs() {
- return new Promise((resolve, reject) => {
- try {
- RNFetchBlob.getEnvironmentDirs((...dirs) => {
- let [PictureDir, MovieDir, DocumentDir, CacheDir] = [...dirs]
- resolve({PictureDir, MovieDir, DocumentDir, CacheDir})
- })
- } catch(err) {
- reject(err)
- }
- })
-
- }
-
- function config (options:fetchConfig) {
- return { fetch : fetch.bind(options) }
- }
-
- // Promise wrapper function
- function fetch(...args:any) {
-
- let options = this || {}
-
- // create task ID for receiving progress event
- let taskId = getUUID()
-
- let promise = new Promise((resolve, reject) => {
-
- let [method, url, headers, body] = [...args]
- let nativeMethodName = Array.isArray(body) ? 'fetchBlobForm' : 'fetchBlob'
-
- // on progress event listener
- let subscription = emitter.addListener('RNFetchBlobProgress', (e) => {
- if(e.taskId === taskId && promise.onProgress) {
- promise.onProgress(e.written, e.total)
- }
- })
-
- let req = RNFetchBlob[nativeMethodName]
- req(options, taskId, method, url, headers || {}, body, (err, ...data) => {
-
- // task done, remove event listener
- subscription.remove()
- if(err)
- reject(new Error(err, ...data))
- else {
- let respType = 'base64'
- if(options.path || options.fileCache)
- respType = 'path'
- resolve(new FetchBlobResponse(taskId, respType, ...data))
- }
-
- })
-
- })
-
- promise.progress = (fn) => {
- promise.onProgress = fn
- return promise
- }
-
- return promise
-
- }
-
- /**
- * RNFetchBlob response object class.
- */
- class FetchBlobResponse {
-
- taskId : string;
- path : () => string | null;
- type : 'base64' | 'path';
- data : any;
- blob : (contentType:string, sliceSize:number) => null;
- text : () => string;
- json : () => any;
- base64 : () => any;
- flush : () => void;
- readStream : (
- encode: 'utf8' | 'ascii' | 'base64',
- fn:(event : 'data' | 'end', chunk:any) => void
- ) => void;
-
- constructor(taskId:string, type:'base64' | 'path', data:any) {
- this.data = data
- this.taskId = taskId
- this.type = type
- /**
- * Convert result to javascript Blob object.
- * @param {string} contentType MIME type of the blob object.
- * @param {number} sliceSize Slice size.
- * @return {blob} Return Blob object.
- */
- this.blob = (contentType:string, sliceSize:number) => {
- console.warn('FetchBlobResponse.blob() is deprecated and has no funtionality.')
- return null
- }
- /**
- * Convert result to text.
- * @return {string} Decoded base64 string.
- */
- this.text = ():string => {
- return base64.decode(this.data)
- }
- /**
- * Convert result to JSON object.
- * @return {object} Parsed javascript object.
- */
- this.json = ():any => {
- return JSON.parse(base64.decode(this.data))
- }
- /**
- * Return BASE64 string directly.
- * @return {string} BASE64 string of response body.
- */
- this.base64 = ():string => {
- return this.data
- }
- /**
- * Remove cahced file
- * @return {void}
- */
- this.flush = () => {
- RNFetchBlob.flush(this.path())
- }
-
- this.path = () => {
- if(this.type === 'path')
- return this.data
- return null
- }
-
- /**
- * Start read stream from cached file
- * @param {String} encoding Encode type, should be one of `base64`, `ascrii`, `utf8`.
- * @param {Function} fn On data event handler
- * @return {void}
- */
- this.readStream = (encode: 'base64' | 'utf8' | 'ascii', fn) => {
-
- // register for file stream event
- let subscription = emitter.addListener(`RNFetchBlobStream${this.taskId}`, (event, chunk) => {
- fn(event, chunk)
- // when stream closed, remove event handler
- if(event === 'end')
- subscription()
- })
-
- if(this.type === 'path') {
- RNFetchBlob.readStream(this.data, encode)
- }
- else {
- console.warn('RNFetchblob', 'this response data does not contains any available stream')
- }
-
- }
-
- }
-
- }
-
- function getUUID(){
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
- let r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
- return v.toString(16);
- });
- }
-
- export default {
- fetch, base64, config, getSystemDirs
- }
|