Bläddra i källkod

update README.md in src folder

Ben Hsieh 8 år sedan
förälder
incheckning
4ec5f1c0c1
1 ändrade filer med 657 tillägg och 26 borttagningar
  1. 657
    26
      src/README.md

+ 657
- 26
src/README.md Visa fil

@@ -1,33 +1,38 @@
1
-# react-native-fetch-blob [![npm version](https://badge.fury.io/js/react-native-fetch-blob.svg)](https://badge.fury.io/js/react-native-fetch-blob)
1
+# react-native-fetch-blob [![npm version](https://badge.fury.io/js/react-native-fetch-blob.svg)](https://badge.fury.io/js/react-native-fetch-blob) ![](https://img.shields.io/badge/PR-Welcome-brightgreen.svg)
2 2
 
3
-A react-native module for fetch file/image with custom headers, supports blob response data, and upload/download progress.
3
+A module provides upload, download, and files access API. Supports file stream read/write for process large files.
4 4
 
5
-If you're dealing with image or file server that requires an `Authorization` token in the header, or you're having problem with `fetch` API when receiving blob data, you might try this module (this is also the reason why I made this).
5
+**Why do we need this**
6 6
 
7
-See [[fetch] Does fetch with blob() marshal data across the bridge?](https://github.com/facebook/react-native/issues/854).
7
+At this moment, React Native does not support `Blob` object yet, so if you're going to send/receive binary data via `fetch` API, that might not work as you expect. See [[fetch] Does fetch with blob() marshal data across the bridge?](https://github.com/facebook/react-native/issues/854).
8 8
 
9
-This module enables you upload/download binary data in js, see [Examples](#user-content-usage) bellow.
9
+Hence you may getting into trouble in some use cases. For example, displaying an image on image server but the server requires a specific field(such as "Authorization") in headers or body, so you can't just pass the image uri to `Image` component because that will probably returns a 401 response. With help of this module, you can send a HTTP request with any headers, and decide how to handle the response/reqeust data. It can be just simply converted into BASE64 string, or store to a file directly so that you can read it by file stream or use it's path.
10 10
 
11
-The source code is very simple, just an implementation of native HTTP request, supports both Android (uses awesome native library  [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client])) and IOS.
11
+This module is designed to be a substitution of `blob`, there's a set of file access API including basic CRUD method, and file stream reader/writer. Also it has a special `fetch` implementation that supports binary request/response body.
12 12
 
13
-## Major Changes
13
+**Pre v0.5.0 Users**
14 14
 
15
-| Version | |
16
-|---|---|
17
-| 0.3 | Upload/Download octet-stream and form-data |
18
-| 0.4 | Add base-64 encode/decode library and API |
19
-| 0.4.1 | Fixe upload form-data missing file extension problem on Android |
20
-| 0.4.2 | Supports upload/download progress |
15
+This update is `backward-compatible` generally you don't have to change existing code unless you're going to use new APIs. In latest version (v0.5.0), 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-usage) bellow. This module implements native methods, supports both Android (uses awesome native library  [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client])) and IOS.
21 16
 
22
-## Usage
17
+## TOC
23 18
 
24 19
 * [Installation](#user-content-installation)
25
-* [Examples](#user-content-usage)
20
+* [Guide](#user-content-guide)
26 21
  * [Download file](#user-content-download-example--fetch-files-that-needs-authorization-token)
27 22
  * [Upload file](#user-content-upload-example--dropbox-files-upload-api)
28 23
  * [Multipart/form upload](#user-content-multipartform-data-example--post-form-data-with-file-and-data)
29 24
  * [Upload/Download progress](#user-content-uploaaddownload-progress)
25
+ * [Android Media Scanner, and Downloads App Support](#user-content-android-media-scanner-and-downloads-app-support)
26
+ * [File access](#user-content-file-access)
27
+ * [File stream](#user-content-file-stream)
28
+ * [Manage cached files](#user-content-manage-cached-files)
30 29
 * [API](#user-content-api)
30
+ * [config](#user-content-config)
31
+ * [fetch](#user-content-fetchmethod-url-headers-bodypromisefetchblobresponse)
32
+ * [session](#user-content-sessionnamestringrnfetchblobsession)
33
+ * [base64](#user-content-base64)
34
+ * [fs](#user-content-fs)
35
+* [Development](#user-content-development)
31 36
 
32 37
 ## Installation
33 38
 
@@ -43,7 +48,26 @@ Link package using [rnpm](https://github.com/rnpm/rnpm)
43 48
 rnpm link
44 49
 ```
45 50
 
46
-## Usage
51
+**Android Access Permission to External storage (Optional)**
52
+
53
+If you're going to access external storage (say, SD card storage), you might have to add the following line to `AndroidManifetst.xml`.
54
+
55
+```diff
56
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
57
+    package="com.rnfetchblobtest"
58
+    android:versionCode="1"
59
+    android:versionName="1.0">
60
+
61
+    <uses-permission android:name="android.permission.INTERNET" />
62
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
63
++   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />                                               
64
++   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />                                              
65
+
66
+    ...
67
+
68
+```
69
+
70
+## Guide
47 71
 
48 72
 ```js
49 73
 import RNFetchBlob from 'react-native-fetch-blob'
@@ -72,6 +96,73 @@ RNFetchBlob.fetch('GET', 'http://www.example.com/images/img1.png', {
72 96
   })
73 97
 ```
74 98
 
99
+#### Download to storage directly
100
+
101
+The simplest way is give a `fileCach` option to config, and set it to `true`. This will let the incoming response data stored in a temporary path **wihout** any file extension.
102
+
103
+**These files won't be removed automatically, please refer to [Cache File Management](#user-content-cache-file-management)**
104
+
105
+```js
106
+RNFetchBlob
107
+  .config({
108
+    // add this option that makes response data to be stored as a file,
109
+    // this is much more performant.
110
+    fileCache : true,
111
+  })
112
+  .fetch('GET', 'http://www.example.com/file/example.zip', {
113
+    some headers ..
114
+  })
115
+  .then((res) => {
116
+    // the temp file path
117
+    console.log('The file saved to ', res.path())
118
+  })
119
+```
120
+
121
+**Set Temp File Extension**
122
+
123
+Sometimes you might need a file extension for some reason. For instance, when using file path as source of `Image` component, the path should end with something like .png or .jpg, you can do this by add `appendExt` option to `config`.
124
+
125
+```js
126
+RNFetchBlob
127
+  .config({
128
+    fileCache : true,
129
+    // by adding this option, the temp files will have a file extension
130
+    appendExt : 'png'
131
+  })
132
+  .fetch('GET', 'http://www.example.com/file/example.zip', {
133
+    some headers ..
134
+  })
135
+  .then((res) => {
136
+    // the temp file path with file extension `png`
137
+    console.log('The file saved to ', res.path())
138
+    // Beware that when using a file path as Image source on Android,
139
+    // you must prepend "file://"" before the file path
140
+    imageView = <Image source={{ uri : Platform.OS === 'android' ? 'file://' : '' + res.path() }}/>
141
+  })
142
+```
143
+
144
+**Use Specific File Path**
145
+
146
+If you prefer a specific path rather than random generated one, you can use `path` option. We've added a constant [dirs](#user-content-dirs) in v0.5.0 that contains several common used directories.
147
+
148
+```js
149
+let dirs = RNFetchBlob.fs.dirs
150
+RNFetchBlob
151
+.config({
152
+  // response data will be saved to this path if it has access right.
153
+  path : dirs.DocumentDir + '/path-to-file.anything'
154
+})
155
+.fetch('GET', 'http://www.example.com/file/example.zip', {
156
+  //some headers ..
157
+})
158
+.then((res) => {
159
+  // the path should be dirs.DocumentDir + 'path-to-file.anything'
160
+  console.log('The file saved to ', res.path())
161
+})
162
+```
163
+
164
+**These files won't be removed automatically, please refer to [Cache File Management](#user-content-cache-file-management)**
165
+
75 166
 ####  Upload example : Dropbox [files-upload](https://www.dropbox.com/developers/documentation/http/documentation#files-upload) API
76 167
 
77 168
 `react-native-fetch-blob` will convert the base64 string in `body` to binary format using native API, this process will be  done in a new thread, so it's async.
@@ -87,6 +178,9 @@ RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
87 178
       mute : false
88 179
     }),
89 180
     'Content-Type' : 'application/octet-stream',
181
+    // here's the body you're going to send, should be a BASE64 encoded string
182
+    // (you can use "base64" APIs to make one).
183
+    // The data will be converted to "byte array"(say, blob) before request sent.  
90 184
   }, base64ImageString)
91 185
   .then((res) => {
92 186
     console.log(res.text())
@@ -96,9 +190,34 @@ RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
96 190
   })
97 191
 ```
98 192
 
193
+#### Upload a file from storage
194
+
195
+If you're going to use a `file` request body, just wrap the path with `wrap` API.
196
+
197
+```js
198
+RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
199
+    // dropbox upload headers
200
+    Authorization : "Bearer access-token...",
201
+    'Dropbox-API-Arg': JSON.stringify({
202
+      path : '/img-from-react-native.png',
203
+      mode : 'add',
204
+      autorename : true,
205
+      mute : false
206
+    }),
207
+    'Content-Type' : 'application/octet-stream',
208
+    // Change BASE64 encoded data to a file path with prefix `RNFetchBlob-file://` when the data comes from a file.
209
+  }, RNFetchBlob.wrap(PATH_TO_THE_FILE))
210
+  .then((res) => {
211
+    console.log(res.text())
212
+  })
213
+  .catch((err) => {
214
+    // error handling ..
215
+  })
216
+```
217
+
99 218
 #### Multipart/form-data example : Post form data with file and data
100 219
 
101
-In `version >= 0.3.0` you can also post files with form data,  just put an array in `body`, with object elements with property `name`, `data`, and `filename`(optional).
220
+In `version >= 0.3.0` you can also post files with form data, just put an array in `body`, with elements have property `name`, `data`, and `filename`(optional).
102 221
 
103 222
 Elements have property `filename` will be transformed into binary format, otherwise it turns into utf8 string.
104 223
 
@@ -124,6 +243,36 @@ Elements have property `filename` will be transformed into binary format, otherw
124 243
   })
125 244
 ```
126 245
 
246
+What if you want to upload a file in some field ? Just like [upload a file from storage](#user-content-upload-a-file-from-storage) example, wrap `data` by `wrap` API (this feature is only available for `version >= v0.5.0`)
247
+
248
+```js
249
+
250
+  RNFetchBlob.fetch('POST', 'http://www.example.com/upload-form', {
251
+    Authorization : "Bearer access-token",
252
+    otherHeader : "foo",
253
+    // this is required, otherwise it won't be process as a multipart/form-data request
254
+    'Content-Type' : 'multipart/form-data',
255
+  }, [
256
+    // append field data from file path
257
+    {
258
+      name : 'avatar',
259
+      filename : 'avatar.png',
260
+      // Change BASE64 encoded data to a file path with prefix `RNFetchBlob-file://` when the data comes from a file path
261
+      data: RNFetchBlob.wrap(PATH_TO_THE_FILE)
262
+    },
263
+    // elements without property `filename` will be sent as plain text
264
+    { name : 'name', data : 'user'},
265
+    { name : 'info', data : JSON.stringify({
266
+      mail : 'example@example.com',
267
+      tel : '12345678'
268
+    })},
269
+  ]).then((resp) => {
270
+    // ...
271
+  }).catch((err) => {
272
+    // ...
273
+  })
274
+```
275
+
127 276
 #### Upload/Download progress
128 277
 
129 278
 In `version >= 0.4.2` it is possible to know the upload/download progress.
@@ -144,10 +293,202 @@ In `version >= 0.4.2` it is possible to know the upload/download progress.
144 293
     })
145 294
 ```
146 295
 
296
+#### Android Media Scanner, and Downloads App Support
297
+
298
+If you want to make a file in `External Storage` becomes visible in Picture, Misuc, or other built-in apps, you will have to use `Media Scanner`. To make this happend, use `scanFile` method in `fs`.
299
+
300
+
301
+```js
302
+
303
+RNFetchBlog
304
+    .config({
305
+        // DCIMDir is in external storage
306
+        path : dirs.DCIMDir + '/music.mp3'
307
+    })
308
+    .fetch('GET', 'http://example.com/music.mp3')
309
+    .then((res) => RNFetchBlob.fs.scanFile([ { path : res.path(), mime : 'audio/mpeg' } ]))
310
+    .then(() => {
311
+        // scan file success
312
+    })
313
+    .catch((err) => {
314
+        // scan file error
315
+    })
316
+```
317
+
318
+If mime is null or undefined, then the mime type will be inferred from the file extension.
319
+
320
+**Download Notification and Visibiliy in Download App (Android Only)**
321
+
322
+<img src="img/android-notification1.png" width="256">
323
+<img src="img/android-notification2.png" width="256">
324
+
325
+
326
+If you want to download notification or make the stored file visible like the above. You have to add some options to `config`.
327
+
328
+```js
329
+RNFetchBlob.config({
330
+  fileCache : true,
331
+  // android only options, these options be a no-op on IOS
332
+  addAndroidDownloads : {
333
+    // Show notification when response data transmitted
334
+    notification : true,
335
+    // Title of download notification
336
+    title : 'Great ! Download Success ! :O ',
337
+    // File description (not notification description)
338
+    description : 'An image file.',
339
+    mime : 'image/png',
340
+    // Make the file scannable  by media scanner
341
+    meidaScannable : true,
342
+  }
343
+})
344
+.fetch('GET', 'http://example.com/image1.png')
345
+.then(...)
346
+```
347
+
348
+#### File Access
349
+
350
+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 I realized that, it's hard to find a great solution to manage cached files, every one who use this moudle may need those APIs for there cases.
351
+
352
+Here's the list of `fs` APIs
353
+
354
+- dirs
355
+- createFile
356
+- readStream
357
+- writeStream
358
+- unlink
359
+- mkdir
360
+- ls
361
+- mv
362
+- cp
363
+- exists
364
+- isDir
365
+- lstat
366
+- stat
367
+- scanFile (Android Only)
368
+
369
+See [fs chapter](#user-content-fs) for more information
370
+
371
+#### File Stream
372
+
373
+In `v0.5.0` we've added  `writeStream` and `readStream`, which allows your app read/write data from file path. This API creates a file stream, rather than convert whole data into BASE64 encoded string, it's handy when processing **large files**.
374
+
375
+When calling `readStream` method, you have to `open` the stream, and start to read data.
376
+
377
+```js
378
+let data = ''
379
+RNFetchBlob.readStream(
380
+    // encoding, should be one of `base64`, `utf8`, `ascii`
381
+    'base64',
382
+    // file path
383
+    PATH_TO_THE_FILE,
384
+    // (optional) buffer size, default to 4096 (4095 for BASE64 encoded data)
385
+    // when reading file in BASE64 encoding, buffer size must be multiples of 3.
386
+    4095)
387
+.then((ifstream) => {
388
+    ifstream.open()
389
+    ifstream.onData((chunk) => {
390
+      // when encoding is `ascii`, chunk will be an array contains numbers
391
+      // otherwise it will be a string
392
+      data += chunk
393
+    })
394
+    ifstream.onError((err) => {
395
+      console.log('oops', err)
396
+    })
397
+    ifstream.onEnd(() => {  
398
+      <Image source={{ uri : 'data:image/png,base64' + data }}
399
+    })
400
+})
401
+```
402
+
403
+When use `writeStream`, the stream is also opened immediately, but you have to `write`, and `close` by yourself.
404
+
405
+```js
406
+RNFetchBlob.writeStream(
407
+    PATH_TO_FILE,
408
+    // encoding, should be one of `base64`, `utf8`, `ascii`
409
+    'utf8',
410
+    // should data append to existing content ?
411
+    true)
412
+.then((ofstream) => {
413
+    ofstream.write('foo')
414
+    ofstream.write('bar')
415
+    ofstream.close()
416
+})
417
+
418
+```
419
+
420
+#### Cache File Management
421
+
422
+When using `fileCache` or `path` options along with `fetch` API, response data will automatically stored into file system. The files will **NOT** removed unless you `unlink` it. There're several ways to remove the files
423
+
424
+```js
425
+
426
+  // remove file using RNFetchblobResponse.flush() object method
427
+  RNFetchblob.config({
428
+      fileCache : true
429
+    })
430
+    .fetch('GET', 'http://example.com/download/file')
431
+    .then((res) => {
432
+      // remove cached file from storage
433
+      res.flush()
434
+    })
435
+
436
+  // remove file by specifying a path
437
+  RNFetchBlob.fs.unlink('some-file-path').then(() => {
438
+    // ...
439
+  })
440
+
441
+```
442
+
443
+You can also grouping requests by using `session` API, and use `dispose` to remove them all when needed.
444
+
445
+```js
446
+
447
+  RNFetchblob.config({
448
+    fileCache : true
449
+  })
450
+  .fetch('GET', 'http://example.com/download/file')
451
+  .then((res) => {
452
+    // set session of a response
453
+    res.session('foo')
454
+  })  
455
+
456
+  RNFetchblob.config({
457
+    // you can also set session beforehand
458
+    session : 'foo'
459
+    fileCache : true
460
+  })
461
+  .fetch('GET', 'http://example.com/download/file')
462
+  .then((res) => {
463
+    // ...
464
+  })  
465
+
466
+  // or put an existing file path to the session
467
+  RNFetchBlob.session('foo').add('some-file-path')
468
+  // remove a file path from the session
469
+  RNFetchBlob.session('foo').remove('some-file-path')
470
+  // list paths of a session
471
+  RNFetchBlob.session('foo').list()
472
+  // remove all files in a session
473
+  RNFetchBlob.session('foo').dispose().then(() => { ... })
474
+
475
+```
476
+
477
+---
147 478
 
148 479
 ## API
149 480
 
150
-#### `fetch(method, url, headers, body):Promise<FetchBlobResponse>`
481
+### `config(options:RNFetchBlobConfig):fetch`
482
+
483
+`0.5.0`
484
+
485
+Config API was introduced in `v0.5.0` which provides some options for the `fetch` task.
486
+
487
+see [RNFetchBlobConfig](#user-content-rnfetchblobconfig)
488
+
489
+### `fetch(method, url, headers, body):Promise<FetchBlobResponse>`
490
+
491
+`legacy`
151 492
 
152 493
 Send a HTTP request uses given headers and body, and return a Promise.
153 494
 
@@ -161,7 +502,9 @@ Headers of HTTP request, value of headers should be `stringified`, if you're upl
161 502
 Body of the HTTP request, body can either be a BASE64 string, or an array contains object elements, each element have 2  required property `name`, and `data`, and 1 optional property `filename`, once `filename` is set, content in `data` property will be consider as BASE64 string that will be converted into byte array later.
162 503
 When body is a base64 string , this string will be converted into byte array in native code, and the request body will be sent as `application/octet-stream`.
163 504
 
164
-### `fetch(...).progress(eventListener):Promise<FetchBlobResponse>` added in `0.4.2`
505
+### `fetch(...).progress(eventListener):Promise<FetchBlobResponse>`
506
+
507
+`0.4.2`
165 508
 
166 509
 Register on progress event handler for a fetch request.
167 510
 
@@ -169,16 +512,249 @@ Register on progress event handler for a fetch request.
169 512
 
170 513
 A function that triggers when there's data received/sent, first argument is the number of sent/received bytes, and second argument is expected total bytes number.
171 514
 
172
-#### `base64`
515
+#### `session(name:string):RNFetchBlobSession`
516
+
517
+TODO
518
+
519
+### `base64`
520
+
521
+
522
+`0.4.2`
173 523
 
174
-A helper object simply uses [base-64](https://github.com/mathiasbynens/base64) for decode and encode BASE64 data.
524
+A helper class simply uses [base-64](https://github.com/mathiasbynens/base64) for decode and encode BASE64 data.
175 525
 
176 526
 ```js
177 527
 RNFetchBlob.base64.encode(data)
178 528
 RNFetchBlob.base64.decode(data)
179 529
 ```
180 530
 
181
-### FetchBlobResponse
531
+### `fs`
532
+
533
+`0.5.0`
534
+
535
+#### dirs
536
+
537
+This constant is a hash map contains common used folders:
538
+- DocumentDir
539
+- CacheDir
540
+- DCIMDir (Android Only)
541
+- DownloadDir (Android Only)
542
+- MusicDir (Android Only)
543
+- PictureDir (Android Only)
544
+- MovieDir (Android Only)
545
+- RingtoneDir (Android Only)
546
+
547
+```js
548
+const dirs = RNFetchBlob.fs.dirs
549
+console.log(dirs.DocumentDir)
550
+console.log(dirs.CacheDir)
551
+console.log(dirs.DCIMDir)
552
+console.log(dirs.DownloadDir)
553
+```
554
+> If you're going to make downloaded file visible in Android `Downloads` app, please see [Show Downloaded File and Notification in Android Downloads App](#user-content-show-downloaded-file-and-notifiction-in-android-downloads-app).
555
+
556
+### createFile(path, data, encoding):Promise
557
+
558
+#### path:`string`
559
+The path which this new file will be created.
560
+#### data:`string` | `Array<number>`
561
+Content of the new file, when `encoding` is `ascii`, this argument shoud be an array contains number 0~255.
562
+#### encoding:`utf8` | `base64` | `ascii`
563
+Encoding of content.
564
+
565
+the following expressions are equivalent.
566
+
567
+```js
568
+const fs = RNFetchBlob.fs
569
+const base64 = RNFetchBlob.base64
570
+fs.createFile(NEW_FILE_PATH, 'foo', 'utf8')
571
+fs.createFile(NEW_FILE_PATH, [102, 111, 111], 'ascii')
572
+fs.createFile(NEW_FILE_PATH, base64.encode('foo'), 'base64')
573
+```
574
+
575
+### writeStream(path:string, encoding:string, append:boolean):Promise<WriteStream>
576
+
577
+#### path:`string`
578
+The path to the file the stream is writing to.
579
+#### encoding:`utf8` | `base64` | `ascii`
580
+Encoding of input data.
581
+#### append:`boolean`(optional, default to `false`)
582
+Will new data append after existing file or not.
583
+
584
+Calling `writeStream` method will returns a Promise, which resolves a `RNFetchBlobWriteSteam` instance when stream opened successfully.
585
+
586
+```js
587
+// write utf8 data
588
+RNFetchBlob.fs.writeStream(PATH_TO_WRITE, 'utf8')
589
+    .then((stream) => {
590
+        stream.write('foo')
591
+        return stream.close()
592
+    })
593
+// write ASCII data
594
+RNFetchBlob.fs.writeStream(PATH_TO_WRITE, 'ascii')
595
+    .then((stream) => {
596
+        // write char `f`
597
+        stream.write([102])
598
+        // write char `o`, `o`
599
+        stream.write([111,111])
600
+        return stream.close()
601
+    })
602
+// write BASE64
603
+RNFetchBlob.fs.writeStream(PATH_TO_WRITE, 'base64')
604
+    .then((stream) => {
605
+        stream.write(RNFetchBlob.base64.encode('foo'))
606
+        return stream.close()
607
+    })
608
+
609
+```
610
+
611
+#### readStream(path, encoding, bufferSize):Promise<ReadStream>
612
+
613
+##### path:`string`
614
+The path to the file the stream is reading from.
615
+##### encoding:`string`
616
+Encoding of the data.
617
+##### bufferSize:`number`(optional)
618
+Buffer size of read stream, default to `4096` and `4095`(when encoding is `base64`)
619
+
620
+`readStream` returns a promise which will resolve `RNFetchBlobReadStream`.
621
+
622
+```js
623
+RNFetchBlob.fs.readStream(PATH_TO_READ, 'utf8')
624
+    .then((stream) => {
625
+        let data = ''
626
+        stream.open()
627
+        stream.onData((chunk) => {
628
+            chunk += data
629
+        })
630
+        stream.onEnd(() => {
631
+            console.log(data)
632
+        })
633
+    })
634
+```
635
+
636
+#### mkdir(path:string):Promise
637
+
638
+Create a directory named `path`
639
+
640
+```js
641
+RNFetchBlob.fs.mkdir(PATH_TO_CREATE)
642
+.then(() => { ... })
643
+.catch((err) => { ... })
644
+```
645
+
646
+#### ls(path:string):Promise<Array<String>>
647
+
648
+List files and directories in a `path`
649
+
650
+```js
651
+RNFetchBlob.fs.ls(PATH_TO_LIST)
652
+    // files will an array contains filenames
653
+    .then((files) => {
654
+        console.log(files)
655
+    })
656
+```
657
+
658
+#### mv(from:string, to:string):Promise
659
+
660
+Move a file's location
661
+
662
+```js
663
+RNFetchBlob.fs.mv(FROM_PATH, TO_PATH)
664
+.then(() => { ... })
665
+.catch(() => { ... })
666
+```
667
+
668
+#### cp(src:string, dest:string):Promise
669
+
670
+Copy a file.
671
+
672
+```js
673
+RNFetchBlob.fs.mv(SRC_PATH, DEST_PATH)
674
+.then(() => { ... })
675
+.catch(() => { ... })
676
+```
677
+
678
+#### exists(path:string):Promise<boolean>
679
+
680
+Check if a file exist at `path`
681
+
682
+```js
683
+RNFetchBlob.fs.exists(PATH_OF_FILE)
684
+.then((exist) => {
685
+    console.log(`file ${exist ? '' : 'not'} exists`)
686
+})
687
+.catch(() => { ... })
688
+```
689
+
690
+#### isDir(path:string):Promise<boolean>
691
+
692
+Check the file at `path` is a directory or not. Resolves with `false` when the path is not a directory, or it does not exists.
693
+
694
+```js
695
+RNFetchBlob.fs.exists(PATH_OF_FILE)
696
+.then((isDir) => {
697
+    console.log(`file is ${isDir ? '' : 'not'} a directory`)
698
+})
699
+```
700
+
701
+#### unlink(path:string):Promise<boolean>
702
+
703
+Delete a file at `path`
704
+
705
+```js
706
+RNFetchBlob.fs.unlink(path)
707
+.then(() => { ... })
708
+.catch((err) => { ... })
709
+```
710
+
711
+#### lstat(path:string):Promise<RNFetchBlobStat>
712
+
713
+Get statistic data of files in a directory, the result data will be an array of [RNFetchBlobStat](#user-content-rnfetchblobstat).
714
+
715
+```js
716
+RNFetchBlob.fs.lstat(PATH_OF_A_FOLDER)
717
+    .then((stats) => {})
718
+    .catch((err) => {})
719
+```
720
+
721
+#### stat(path:string):Promise<RNFetchBlobStat>
722
+
723
+Similar get statistic a data or a directory. the result data will be a [RNFetchBlobStat](#user-content-rnfetchblobstat).
724
+
725
+```js
726
+RNFetchBlob.fs.stat(PATH_OF_THE_TARGET)
727
+    .then((stats) => {})
728
+    .catch((err) => {})
729
+```
730
+
731
+#### scanFile(path:string):Promise (Androi Only)
732
+
733
+Connect `Media Scanner` and scan the file. see [Android Media Scanner, and Downloads App Support](#user-content-android-media-scanner-and-downloads-app-support) chapter for more information.
734
+
735
+---
736
+
737
+## Types
738
+
739
+### RNFetchBlobConfig
740
+
741
+A set of configurations that will be injected into a `fetch` method, with the following properties.
742
+
743
+#### fileCache:boolean
744
+  Set this property to `true` will makes response data of the `fetch` stored in a temp file, by default the temp file will stored in App's own root folder with file name template `RNFetchBlob_tmp${timestamp}`.
745
+#### appendExt:string
746
+  Set this propery to change temp file extension that created by `fetch` response data.
747
+#### path:string
748
+  When this property has value, `fetch` API will try to store response data in the path ignoring `fileCache` and `appendExt` property.
749
+#### addAndroidDownloads:object (Android only)
750
+  This is an Android only property, it should be an object with the following properties :
751
+  - title : title of the file
752
+  - description : File description of the file.
753
+  - mime : MIME type of the file. By default is `text/plain`
754
+  - mediaScannable : A `boolean` value, see [Officail Document](https://developer.android.com/reference/android/app/DownloadManager.html#addCompletedDownload(java.lang.String, java.lang.String, boolean, java.lang.String, java.lang.String, long, boolean))
755
+  - notification : A `boolean` value decide whether show a notification when download complete.
756
+
757
+### RNFetchBlobResponse
182 758
 
183 759
 When `fetch` success, it resolve a `FetchBlobResponse` object as first argument. `FetchBlobResponse` object has the following methods (these method are synchronous, so you might take quite a performance impact if the file is big)
184 760
 
@@ -188,10 +764,65 @@ When `fetch` success, it resolve a `FetchBlobResponse` object as first argument.
188 764
   returns json parsed object (done in js context)
189 765
 #### text():string
190 766
   returns decoded base64 string (done in js context)
767
+#### path():string
768
+  returns file path if the response data is cached in file
769
+#### session(name:string):RNFetchBlobSession
770
+  when the response data is cached in a file, this method adds the file into the session. The following usages are equivalent.
771
+```js
772
+RNFetchBlob.session('session-name').add(resp.path())
773
+// or
774
+resp.session('session-name')
775
+```
776
+
777
+### RNFetchBlobStat
778
+
779
+Statistic data of a file, see the following sample object.
780
+
781
+```js
782
+{
783
+    // file name
784
+    filename : 'foo.png',
785
+    // folder of the file or the folder itself
786
+    path : '/path/to/the/file/wihout/file/name/',
787
+    // size in byte
788
+    size : 4901,
789
+    // `file` or `directory`
790
+    type : 'file',
791
+    // last modified timestamp
792
+    lastModified : 141323298
793
+}
794
+```
795
+
796
+
797
+### RNFetchBlobSession
798
+
799
+A `session` is an object that helps you manage files. It simply main a list of file path and let you use `dispose()`to delete files in this session once and for all.
800
+
801
+#### add(path:string):RNFetchBlobSession
802
+  Add a file path to this session.
803
+#### remove(path:string):RNFetchBlobSession
804
+  Remove a file path from this session (not delete the file).
805
+#### list():Array<String>
806
+  Returns an array contains file paths in this session.
807
+#### dispose():Promise
808
+  Delete all files according to paths in the session.
809
+
810
+## Major Changes
811
+
812
+| Version | |
813
+|---|---|
814
+| 0.5.0 | Upload/download with direct access to file storage, and also added file access APIs |
815
+| 0.4.2 | Supports upload/download progress |
816
+| 0.4.1 | Fixe upload form-data missing file extension problem on Android |
817
+| 0.4.0 | Add base-64 encode/decode library and API |
818
+| ~0.3.0 | Upload/Download octet-stream and form-data |
819
+
820
+### TODOs
191 821
 
822
+* Customizable Multipart MIME type
823
+* Improvement of file cache management API
192 824
 
193
-### Upcoming Features
825
+### Development
194 826
 
195
-* Save file to storage directly
196
-* Upload file from storage directly
197
-* Custom MIME type in form data
827
+If you're interested in hacking this module, check our [development guide](https://github.com/wkh237/react-native-fetch-blob/wiki/Development-Guide), there might be some helpful information.
828
+Please feel free to make a PR or file an issue.