|  | @@ -16,6 +16,7 @@ import type {
 | 
	
		
			
			| 16 | 16 |    RNFetchBlobStream,
 | 
	
		
			
			| 17 | 17 |    RNFetchBlobResponseInfo
 | 
	
		
			
			| 18 | 18 |  } from './types'
 | 
	
		
			
			|  | 19 | +import URIUtil from './utils/uri'
 | 
	
		
			
			| 19 | 20 |  import StatefulPromise from './class/StatefulPromise.js'
 | 
	
		
			
			| 20 | 21 |  import fs from './fs'
 | 
	
		
			
			| 21 | 22 |  import getUUID from './utils/uuid'
 | 
	
	
		
			
			|  | @@ -100,6 +101,86 @@ function config (options:RNFetchBlobConfig) {
 | 
	
		
			
			| 100 | 101 |    return { fetch : fetch.bind(options) }
 | 
	
		
			
			| 101 | 102 |  }
 | 
	
		
			
			| 102 | 103 |  
 | 
	
		
			
			|  | 104 | +/**
 | 
	
		
			
			|  | 105 | + * Fetch from file system, use the same interface as RNFB.fetch
 | 
	
		
			
			|  | 106 | + * @param  {RNFetchBlobConfig} [options={}] Fetch configurations
 | 
	
		
			
			|  | 107 | + * @param  {string} method     Should be one of `get`, `post`, `put`
 | 
	
		
			
			|  | 108 | + * @param  {string} url        A file URI string
 | 
	
		
			
			|  | 109 | + * @param  {string} headers    Arguments of file system API
 | 
	
		
			
			|  | 110 | + * @param  {any} body       Data to put or post to file systen.
 | 
	
		
			
			|  | 111 | + * @return {Promise}
 | 
	
		
			
			|  | 112 | + */
 | 
	
		
			
			|  | 113 | +function fetchFile(options = {}, method, url, headers = {}, body):Promise {
 | 
	
		
			
			|  | 114 | +
 | 
	
		
			
			|  | 115 | +  if(!URIUtil.isFileURI(url)) {
 | 
	
		
			
			|  | 116 | +    throw `could not fetch file from an invalid URI : ${url}`
 | 
	
		
			
			|  | 117 | +  }
 | 
	
		
			
			|  | 118 | +
 | 
	
		
			
			|  | 119 | +  url = URIUtil.unwrapFileURI(url)
 | 
	
		
			
			|  | 120 | +
 | 
	
		
			
			|  | 121 | +  let promise = null
 | 
	
		
			
			|  | 122 | +  let cursor = 0
 | 
	
		
			
			|  | 123 | +  let total = -1
 | 
	
		
			
			|  | 124 | +  let cacheData = ''
 | 
	
		
			
			|  | 125 | +  let info = null
 | 
	
		
			
			|  | 126 | +
 | 
	
		
			
			|  | 127 | +  let _progress, _uploadProgress, _stateChange
 | 
	
		
			
			|  | 128 | +
 | 
	
		
			
			|  | 129 | +  switch(method.toLowerCase()) {
 | 
	
		
			
			|  | 130 | +
 | 
	
		
			
			|  | 131 | +    case 'post':
 | 
	
		
			
			|  | 132 | +    break
 | 
	
		
			
			|  | 133 | +
 | 
	
		
			
			|  | 134 | +    case 'put':
 | 
	
		
			
			|  | 135 | +    break
 | 
	
		
			
			|  | 136 | +
 | 
	
		
			
			|  | 137 | +    // read data from file system
 | 
	
		
			
			|  | 138 | +    default:
 | 
	
		
			
			|  | 139 | +      promise = fs.stat(url)
 | 
	
		
			
			|  | 140 | +      .then((stat) => {
 | 
	
		
			
			|  | 141 | +        total = stat.size
 | 
	
		
			
			|  | 142 | +        return fs.readStream(url, headers.encoding || 'utf8', Math.floor(headers.bufferSize) || 4096)
 | 
	
		
			
			|  | 143 | +      })
 | 
	
		
			
			|  | 144 | +      .then((stream) => new Promise((resolve, reject) => {
 | 
	
		
			
			|  | 145 | +        stream.open()
 | 
	
		
			
			|  | 146 | +        info = {
 | 
	
		
			
			|  | 147 | +          state : "2",
 | 
	
		
			
			|  | 148 | +          headers : { 'source' : 'system-fs' },
 | 
	
		
			
			|  | 149 | +          status : 200,
 | 
	
		
			
			|  | 150 | +          respType : 'text',
 | 
	
		
			
			|  | 151 | +          rnfbEncode : headers.encoding || 'utf8'
 | 
	
		
			
			|  | 152 | +        }
 | 
	
		
			
			|  | 153 | +        _stateChange(info)
 | 
	
		
			
			|  | 154 | +        stream.onData((chunk) => {
 | 
	
		
			
			|  | 155 | +          _progress && _progress(cursor, total, chunk)
 | 
	
		
			
			|  | 156 | +          if(headers.noCache)
 | 
	
		
			
			|  | 157 | +            return
 | 
	
		
			
			|  | 158 | +          cacheData += chunk
 | 
	
		
			
			|  | 159 | +        })
 | 
	
		
			
			|  | 160 | +        stream.onError((err) => { reject(err) })
 | 
	
		
			
			|  | 161 | +        stream.onEnd(() => {
 | 
	
		
			
			|  | 162 | +          resolve(new FetchBlobResponse(null, info, cacheData))
 | 
	
		
			
			|  | 163 | +        })
 | 
	
		
			
			|  | 164 | +      }))
 | 
	
		
			
			|  | 165 | +    break
 | 
	
		
			
			|  | 166 | +  }
 | 
	
		
			
			|  | 167 | +
 | 
	
		
			
			|  | 168 | +  promise.progress = (fn) => {
 | 
	
		
			
			|  | 169 | +    _progress = fn
 | 
	
		
			
			|  | 170 | +    return promise
 | 
	
		
			
			|  | 171 | +  }
 | 
	
		
			
			|  | 172 | +  promise.stateChange = (fn) => {
 | 
	
		
			
			|  | 173 | +    _stateChange = fn
 | 
	
		
			
			|  | 174 | +    return promise
 | 
	
		
			
			|  | 175 | +  }
 | 
	
		
			
			|  | 176 | +  promise.uploadProgress = (fn) => {
 | 
	
		
			
			|  | 177 | +    _uploadProgress = fn
 | 
	
		
			
			|  | 178 | +    return promise
 | 
	
		
			
			|  | 179 | +  }
 | 
	
		
			
			|  | 180 | +
 | 
	
		
			
			|  | 181 | +  return promise
 | 
	
		
			
			|  | 182 | +}
 | 
	
		
			
			|  | 183 | +
 | 
	
		
			
			| 103 | 184 |  /**
 | 
	
		
			
			| 104 | 185 |   * Create a HTTP request by settings, the `this` context is a `RNFetchBlobConfig` object.
 | 
	
		
			
			| 105 | 186 |   * @param  {string} method HTTP method, should be `GET`, `POST`, `PUT`, `DELETE`
 | 
	
	
		
			
			|  | @@ -119,9 +200,15 @@ function fetch(...args:any):Promise {
 | 
	
		
			
			| 119 | 200 |    let options = this || {}
 | 
	
		
			
			| 120 | 201 |    let subscription, subscriptionUpload, stateEvent
 | 
	
		
			
			| 121 | 202 |    let respInfo = {}
 | 
	
		
			
			|  | 203 | +  let [method, url, headers, body] = [...args]
 | 
	
		
			
			|  | 204 | +
 | 
	
		
			
			|  | 205 | +  // fetch from file system
 | 
	
		
			
			|  | 206 | +  if(URIUtil.isFileURI(url)) {
 | 
	
		
			
			|  | 207 | +    return fetchFile(options, method, url, headers, body)
 | 
	
		
			
			|  | 208 | +  }
 | 
	
		
			
			| 122 | 209 |  
 | 
	
		
			
			|  | 210 | +  // from remote HTTP(S)
 | 
	
		
			
			| 123 | 211 |    let promise = new Promise((resolve, reject) => {
 | 
	
		
			
			| 124 |  | -    let [method, url, headers, body] = [...args]
 | 
	
		
			
			| 125 | 212 |      let nativeMethodName = Array.isArray(body) ? 'fetchBlobForm' : 'fetchBlob'
 | 
	
		
			
			| 126 | 213 |  
 | 
	
		
			
			| 127 | 214 |      // on progress event listener
 |