-
Notifications
You must be signed in to change notification settings - Fork 787
Fetch API
This document contains examples and API specifications of our network module and newly introduced fetch replacement
, basically they're providing the same functionalities, however, the fetch replacement provides a much more familiar development experience.
After
0.9.4
fetch API will not useChunked
encoding by default. You have to explicitly enable it by setting headerTransfer-Encoding
toChunked
.
When you store the response data in memory, fetch API automatically decide whether encode the data into BASE64 string, generally when the data contains invalid UTF8 characters you'll get a base64
string, otherwise an utf8
string, however, there might be some inconsistency between IOS and Android, by setting this header, response data will always encode using 'utf8' or 'base64'.
More information #122
config(options:RNFetchBlobConfig:fetch
0.5.0
Config API was introduced in v0.5.0
which provides some options for the fetch
task.
fetch(method, url, headers, body):StatefulPromise
legacy
Send an HTTP request uses given headers and body, and return a Promise.
HTTP request method, can be one of get
, post
, delete
, and put
, case-insensitive.
HTTP request destination URL.
Headers of HTTP request, the value of headers should be stringified
, if you're uploading binary files, content-type should be application/octet-stream
or multipart/form-data
(see examples above).
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
, data
, and optional property filename
, once filename
is set, content in data
property will be considered as a path to a file or a BASE64 string which will be converted into byte array later.
For example
// Post binary data using base64 encoding
RNFetchBlob.fetch('POST', 'http://myupload.com/upload', {
'Content-Type' : 'application/octet-stream'
}, RNFetchBlob.base64.encode(mydata))
// Post binary data from existing file
RNFetchBlob.fetch('POST', 'http://myupload.com/upload', {
'Content-Type' : 'application/octet-stream'
}, RNFetchBlob.wrap(path_to_the_file))
// Post form data
RNFetchBlob.fetch('POST', 'http://myupload.com/upload', {
'Content-Type' : 'multipart/form-data'
}, [
{ name : 'user_name', data : 'Bill' },
// binary field data from a file path, use `wrap` method to wrap the path
{ name : 'avatar', filename : 'avatar.jpg', data : RNFetchBlob.wrap(path_to_the_file) },
// binary field data encoded in BASE64
{ name : 'pet-avatar', filename : 'pet-avatar.jpg', data : RNFetchBlob.base64.encode(image_data) },
])
fetch(...).progress(?config, eventListener):Promise<RNFetchBlobResponse>
0.9.6
Register on progress event handler for a fetch request.After 0.9.6
this method accepts 2 arguments config
and eventListener
, if you're upgrading from the previous version, you don't have to change your code, because the config
is optional.
0.9.6
This argument is optional, when not specifying any object, it uses default config count=-1
, interval=250
.
count
is a number which limits the number of progress event, for example, if count = 1 the progress event will only fire 10 times and the progress should be around 0% 10% 20% ... 90%. However, when a server does not provide response content length this argument will not work.
interval
should be an integer which represents the minimum interval between progress events (in ms), the default value is 250.
A function that triggers when there's data received/sent, the first argument is the number of sent/received bytes, and the second argument is expected total bytes number, totalByte
will be -1
if the server does not provide the response content length.
RNFetchBlob.fetch('GET', 'http://mydownload.com/image/1')
.progress((received, total) => {
console.log('progress ' + Math.floor(received/total*100) + '%')
})
// use custom config (0.9.6+)
RNFetchBlob.fetch('GET', 'http://mydownload.com/image/1')
.progress({ interval : 100 }, (received, total) => {
console.log('progress ' + Math.floor(received/total*100) + '%')
})
fetch(...).uploadProgress(?config, eventListener):Promise<RNFetchBlobResponse>
After 0.9.6
this method accepts 2 arguments config
and eventListener
, if you're upgrading from the previous version, you don't have to change your code, because the config
is optional.
0.9.6
This argument is optional, when not specifying any object, it uses default config count=-1
, interval=250
.
count
is a number which limits the number of progress event, for example, if count = 10 the progress event will only fire 10 times and the progress should be around 0% 10% 20% ... 90%. However, when a server does not provide response content length this argument will not work.
interval
should be an integer which represents minimun interval between progress events (in ms), the default value is 250.
Just like progress
but the listener invoked when data write to HTTP request stream. uploadProgress
is not supported on Android before version 0.7.0
.
// use default configuration
RNFetchBlob.fetch('GET', 'http://mydownload.com/image/1')
.uploadProgress((received, total) => {
console.log('progress ' + Math.floor(received/total*100) + '%')
})
// use custom configuration (0.9.6+)
RNFetchBlob.fetch('GET', 'http://mydownload.com/image/1')
.uploadProgress({ interval : 200 }, (received, total) => {
console.log('progress ' + Math.floor(received/total*100) + '%')
})
The progress event triggers at a very high frequency, it is recommended to add a debounce mechanism when an UI update is triggered by progress event. For example
RNFetchBlob.fetch('GET', 'http://largefile.com/file/1')
.progress((received, total) => {
if(Date.now() - this.state.lastTick < 1000)
return
this.setState({
progress : received/total,
lastTick : Date.now()
})
})
fetch(...).cancel(eventListener):Promise<RNFetchBlobResponse>
0.7.0
Cancel a HTTP request which will cause the fetch
call throw an rejected promise. Argument eventListener
is optional.
let task = RNFetchBlob.fetch('GET', 'http://example.com/file/1')
task.then((data) => {
// .. success
})
.catch((err) => {
console.log(err)
})
// cancel the HTTP request
task.cancel((err, taskId) => {
// task successfully canceled
})
0.9.0
If you have existing code that uses whatwg-fetch, now you don't have to change existing code after 0.9.0
, just use fetch replacement
. The difference between Official fetch
and fetch replacement
is that, official fetch
uses WHATWG-fetch js library which wraps XMLHttpRequest polyfill
under the hood, and our implementation simply wraps RNFetchBlob.fetch.
import RNFetchBlob from 'rn-fetch-blob';
const Fetch = RNFetchBlob.polyfill.Fetch;
// replace built-in fetch
window.fetch = new Fetch({
// enable this option so that the response data conversion handled automatically
auto : true,
// when receiving response data, the module will match its Content-Type header
// with strings in this array. If it contains any one of string in this array,
// the response body will be considered as binary data and the data will be stored
// in file system instead of in memory.
// By default, it only store response data to file system when Content-Type
// contains string `application/octet`.
binaryContentTypes : [
'image/',
'video/',
'audio/',
'foo/',
]
}).build();
Basically, fetch replacement accepts RNFetchBlob.polyfill.Blob
, RNFetchBlob.polyfill.File
, String
(plain string or BASE64 encoded), and FormData
as its request body. When the body is a BASE64 string, be sure Content-Type
contains string ;BASE64
, or application/octet
, otherwise it won't be converted to binary format.
usage : BASE64 encoded string body
fetch('http://www.example.com/', {
method : 'POST',
'Content-Type' : 'foo/bar;BASE64'
body : base64EncodedString
})
usage : Blob body (how to create a Blob)
When request body is a
FormData
theBlob
in form data will automatically be removed after request sent
window.Blob = RNFetchBlob.polyfill.Blob
// create Blob object (this is not a standard method of Blob class)
Blob.build('blob body').then((b) => {
fetch('http://www.example.com', {
method : 'POST',
body : b
})
})
usage : Multipart form data
window.File = RNFetchBlob.polyfill.File
let form = new FormData()
form.append('user', 'wkh237')
form.append('email', 'xeiyan@gmail.com')
// create first file from BASE64, file IO is asynchronous therefore
// we need wait for the promise.
// The `;BASE64` in `type` is important when creating Blob/File from
// BASE64 encoded data.
File.build('image.png', base64ImageStr, { type: 'image/png;BASE64' })
.then((file) => {
// add the file to form data
form.append('avatar', file)
// create File object from existing file path, the content type is optional
return File.build('image2.png', RNFetchBlob.wrap(pathToAFile), { type: 'image/png' })
})
.then((file) => {
// add the file to form data, now we have 2 files in form data
form.append('avatar', file)
return fetch('http://www.wkh237.com/upload', {
method : 'POST',
body : form
})
})
.then((res) => ...)
...
When using fetch replacement, the fetch
calls will return a StatefulPromise, it's an object extends Promise
, which allows you attach upload/download progress listener to it, and also it allows you cancel the task.
let promise = fetch('http://www.example.com/test', {
method : 'POST',
body
})
// attach listeners
promise.progress((loaded, total )= > { console.log(`${Math.floor(loaded/total*100)}% downloaded`) })
promise.uploadProgress((loaded, total )= > { console.log(`${Math.floor(loaded/total*100)}% uploaded`) })
// completion handler
promise.then(() => { console.log('OK') })
// cancel the task
promise.cancel()
By default, fetch replacement determines whether to store response data in the file system by checking Content-Type
in the response header, the basic rule is, when Content-Type
contains substring application/octet
the response data will be stored in file system. You can add more patterns by using binaryContentTypes
property in config
. This is useful when the response data is big because saving response data into file system does not cause memory and performance impact to your app, however, you have to remove the file when it's no longer needed (use fs API).
window.fetch = new RNFetchBlob.polyfill.Fetch({
auto : true,
// now, response with Content-Type contains `image/`, `video/`, and `video/`
// will downloaded into file system directly.
binaryContentTypes : ['image/', 'video/', 'audio/']
}).build()
Instead of standard response object, you can also access RNFB style response object when using fetch replacement
fetch('http://example.com')
.then((res) => {
// the RNFB-style response object
let rnfbResp = res.rawResp()
})