// Copyright 2016 wkh237@github. All rights reserved. // Use of this source code is governed by a MIT-style license that can be // found in the LICENSE file. // import type {RNFetchBlobConfig, RNFetchBlobNative, RNFetchBlobStream} from './types' import {NativeModules, Platform} from 'react-native' import RNFetchBlobSession from './class/RNFetchBlobSession' import RNFetchBlobWriteStream from './class/RNFetchBlobWriteStream' import RNFetchBlobReadStream from './class/RNFetchBlobReadStream' import RNFetchBlobFile from './class/RNFetchBlobFile' const RNFetchBlob: RNFetchBlobNative = NativeModules.RNFetchBlob const dirs = { DocumentDir: RNFetchBlob.DocumentDir, CacheDir: RNFetchBlob.CacheDir, PictureDir: RNFetchBlob.PictureDir, MusicDir: RNFetchBlob.MusicDir, MovieDir: RNFetchBlob.MovieDir, DownloadDir: RNFetchBlob.DownloadDir, DCIMDir: RNFetchBlob.DCIMDir, SDCardDir: RNFetchBlob.SDCardDir, SDCardApplicationDir: RNFetchBlob.SDCardApplicationDir, MainBundleDir: RNFetchBlob.MainBundleDir, LibraryDir: RNFetchBlob.LibraryDir } function addCode(code: string, error: Error): Error { error.code = code return error } /** * Get a file cache session * @param {string} name Stream ID * @return {RNFetchBlobSession} */ function session(name: string): RNFetchBlobSession { let s = RNFetchBlobSession.getSession(name) if (s) return new RNFetchBlobSession(name) else { RNFetchBlobSession.setSession(name, []) return new RNFetchBlobSession(name, []) } } function asset(path: string): string { if (Platform.OS === 'ios') { // path from camera roll if (/^assets-library\:\/\//.test(path)) return path } return 'bundle-assets://' + path } function createFile(path: string, data: string, encoding: 'base64' | 'ascii' | 'utf8' = 'utf8'): Promise { if (encoding.toLowerCase() === 'ascii') { return Array.isArray(data) ? RNFetchBlob.createFileASCII(path, data) : Promise.reject(addCode('EINVAL', new TypeError('`data` of ASCII file must be an array with 0..255 numbers'))) } else { return RNFetchBlob.createFile(path, data, encoding) } } /** * Create write stream to a file. * @param {string} path Target path of file stream. * @param {string} encoding Encoding of input data. * @param {boolean} [append] A flag represent if data append to existing ones. * @return {Promise} A promise resolves a `WriteStream` object. */ function writeStream( path: string, encoding?: 'utf8' | 'ascii' | 'base64' = 'utf8', append?: boolean = false, ): Promise { if (typeof path !== 'string') { return Promise.reject(addCode('EINVAL', new TypeError('Missing argument "path" '))) } return new Promise((resolve, reject) => { RNFetchBlob.writeStream(path, encoding, append, (errCode, errMsg, streamId: string) => { if (errMsg) { const err = new Error(errMsg) err.code = errCode reject(err) } else resolve(new RNFetchBlobWriteStream(streamId, encoding)) }) }) } /** * Create file stream from file at `path`. * @param {string} path The file path. * @param {string} encoding Data encoding, should be one of `base64`, `utf8`, `ascii` * @param {boolean} bufferSize Size of stream buffer. * @param {number} [tick=10] Interval in milliseconds between reading chunks of data * @return {RNFetchBlobStream} RNFetchBlobStream stream instance. */ function readStream( path: string, encoding: 'utf8' | 'ascii' | 'base64' = 'utf8', bufferSize?: number, tick?: number = 10 ): Promise { if (typeof path !== 'string') { return Promise.reject(addCode('EINVAL', new TypeError('Missing argument "path" '))) } return Promise.resolve(new RNFetchBlobReadStream(path, encoding, bufferSize, tick)) } /** * Create a directory. * @param {string} path Path of directory to be created * @return {Promise} */ function mkdir(path: string): Promise { if (typeof path !== 'string') { return Promise.reject(addCode('EINVAL', new TypeError('Missing argument "path" '))) } return RNFetchBlob.mkdir(path) } /** * Returns the path for the app group. * @param {string} groupName Name of app group * @return {Promise} */ function pathForAppGroup(groupName: string): Promise { return RNFetchBlob.pathForAppGroup(groupName) } /** * Wrapper method of readStream. * @param {string} path Path of the file. * @param {'base64' | 'utf8' | 'ascii'} encoding Encoding of read stream. * @return {Promise | string>} */ function readFile(path: string, encoding: string = 'utf8'): Promise { if (typeof path !== 'string') { return Promise.reject(addCode('EINVAL', new TypeError('Missing argument "path" '))) } return RNFetchBlob.readFile(path, encoding) } /** * Write data to file. * @param {string} path Path of the file. * @param {string | number[]} data Data to write to the file. * @param {string} encoding Encoding of data (Optional). * @return {Promise} */ function writeFile(path: string, data: string | Array, encoding: ?string = 'utf8'): Promise { if (typeof path !== 'string') { return Promise.reject(addCode('EINVAL', new TypeError('Missing argument "path" '))) } if (encoding.toLocaleLowerCase() === 'ascii') { if (!Array.isArray(data)) { return Promise.reject(addCode('EINVAL', new TypeError('"data" must be an Array when encoding is "ascii"'))) } else return RNFetchBlob.writeFileArray(path, data, false) } else { if (typeof data !== 'string') { return Promise.reject(addCode('EINVAL', new TypeError(`"data" must be a String when encoding is "utf8" or "base64", but it is "${typeof data}"`))) } else return RNFetchBlob.writeFile(path, encoding, data, false) } } function appendFile(path: string, data: string | Array, encoding?: string = 'utf8'): Promise { if (typeof path !== 'string') { return Promise.reject(addCode('EINVAL', new TypeError('Missing argument "path" '))) } if (encoding.toLocaleLowerCase() === 'ascii') { if (!Array.isArray(data)) { return Promise.reject(addCode('EINVAL', new TypeError('`data` of ASCII file must be an array with 0..255 numbers'))) } else return RNFetchBlob.writeFileArray(path, data, true) } else { if (typeof data !== 'string') { return Promise.reject(addCode('EINVAL'), new TypeError(`"data" must be a String when encoding is "utf8" or "base64", but it is "${typeof data}"`)) } else return RNFetchBlob.writeFile(path, encoding, data, true) } } /** * Show statistic data of a path. * @param {string} path Target path * @return {RNFetchBlobFile} */ function stat(path: string): Promise { return new Promise((resolve, reject) => { if (typeof path !== 'string') { return reject(addCode('EINVAL', new TypeError('Missing argument "path" '))) } RNFetchBlob.stat(path, (err, stat) => { if (err) reject(new Error(err)) else { if (stat) { stat.size = parseInt(stat.size) stat.lastModified = parseInt(stat.lastModified) } resolve(stat) } }) }) } /** * Android only method, request media scanner to scan the file. * @param {Array>} pairs Array contains Key value pairs with key `path` and `mime`. * @return {Promise} */ function scanFile(pairs: any): Promise { return new Promise((resolve, reject) => { if (pairs === undefined) { return reject(addCode('EINVAL', new TypeError('Missing argument'))) } RNFetchBlob.scanFile(pairs, (err) => { if (err) reject(addCode('EUNSPECIFIED', new Error(err))) else resolve() }) }) } function hash(path: string, algorithm: string): Promise { if (typeof path !== 'string' || typeof algorithm !== 'string') { return Promise.reject(addCode('EINVAL', new TypeError('Missing argument "path" and/or "algorithm"'))) } return RNFetchBlob.hash(path, algorithm) } function cp(path: string, dest: string): Promise { return new Promise((resolve, reject) => { if (typeof path !== 'string' || typeof dest !== 'string') { return reject(addCode('EINVAL', new TypeError('Missing argument "path" and/or "destination"'))) } RNFetchBlob.cp(path, dest, (err, res) => { if (err) reject(addCode('EUNSPECIFIED', new Error(err))) else resolve(res) }) }) } function mv(path: string, dest: string): Promise { return new Promise((resolve, reject) => { if (typeof path !== 'string' || typeof dest !== 'string') { return reject(addCode('EINVAL', new TypeError('Missing argument "path" and/or "destination"'))) } RNFetchBlob.mv(path, dest, (err, res) => { if (err) reject(addCode('EUNSPECIFIED', new Error(err))) else resolve(res) }) }) } function lstat(path: string): Promise> { return new Promise((resolve, reject) => { if (typeof path !== 'string') { return reject(addCode('EINVAL', new TypeError('Missing argument "path" '))) } RNFetchBlob.lstat(path, (err, stat) => { if (err) reject(addCode('EUNSPECIFIED', new Error(err))) else resolve(stat) }) }) } function ls(path: string): Promise> { if (typeof path !== 'string') { return Promise.reject(addCode('EINVAL', new TypeError('Missing argument "path" '))) } return RNFetchBlob.ls(path) } /** * Remove file at path. * @param {string} path:string Path of target file. * @return {Promise} */ function unlink(path: string): Promise { return new Promise((resolve, reject) => { if (typeof path !== 'string') { return reject(addCode('EINVAL', new TypeError('Missing argument "path" '))) } RNFetchBlob.unlink(path, (err) => { if (err) { reject(addCode('EUNSPECIFIED', new Error(err))) } else resolve() }) }) } /** * Check if file exists and if it is a folder. * @param {string} path Path to check * @return {Promise} */ function exists(path: string): Promise { return new Promise((resolve, reject) => { if (typeof path !== 'string') { return reject(addCode('EINVAL', new TypeError('Missing argument "path" '))) } try { RNFetchBlob.exists(path, (exist) => { resolve(exist) }) }catch (err){ reject(addCode('EUNSPECIFIED', new Error(err))) } }) } function slice(src: string, dest: string, start: number, end: number): Promise { if (typeof src !== 'string' || typeof dest !== 'string') { return reject(addCode('EINVAL', new TypeError('Missing argument "src" and/or "destination"'))) } let p = Promise.resolve() let size = 0 function normalize(num, size) { if (num < 0) return Math.max(0, size + num) if (!num && num !== 0) return size return num } if (start < 0 || end < 0 || !start || !end) { p = p.then(() => stat(src)) .then((stat) => { size = Math.floor(stat.size) start = normalize(start || 0, size) end = normalize(end, size) }) } return p.then(() => RNFetchBlob.slice(src, dest, start, end)) } function isDir(path: string): Promise { return new Promise((resolve, reject) => { if (typeof path !== 'string') { return reject(addCode('EINVAL', new TypeError('Missing argument "path" '))) } try { RNFetchBlob.exists(path, (exist, isDir) => { resolve(isDir) }) }catch (err){ reject(addCode('EUNSPECIFIED', new Error(err))) } }) } function df(): Promise<{ free: number, total: number }> { return new Promise((resolve, reject) => { RNFetchBlob.df((err, stat) => { if (err) reject(addCode('EUNSPECIFIED', new Error(err))) else resolve(stat) }) }) } export default { RNFetchBlobSession, unlink, mkdir, session, ls, readStream, mv, cp, writeStream, writeFile, appendFile, pathForAppGroup, readFile, hash, exists, createFile, isDir, stat, lstat, scanFile, dirs, slice, asset, df }