@@ -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
0 commit comments