Skip to content

Commit bbc34b6

Browse files
committed
Merge remote-tracking branch 'upstream/0.10.9'
* upstream/0.10.9: Fixed problem with type casting (wkh237#513) My proposed 0.10.9 changes (wkh237#489) wkh237#268 Cancelled task should not trigger `then` promise function Add ability to cancel android DownloadManager fetches (wkh237#502) Fix iOS initialization race condition (wkh237#499) prevent UIApplication methods from being called on background thread (wkh237#486) Implemenet fs.hash() -- wkh237#439 "Feature: Calculate file hash" (wkh237#476) I forgot one error string for the Android readFile() method (wkh237#475) Fix for wkh237#467 (wkh237#472) Fix for issue wkh237#468, wkh237#461, wkh237#460 and minor cleanup (wkh237#469)
2 parents 51f8a19 + 4205ebc commit bbc34b6

26 files changed

+1053
-600
lines changed

README.md

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -598,10 +598,12 @@ File Access APIs
598598
- [dirs](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#dirs)
599599
- [createFile](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#createfilepath-data-encodingpromise)
600600
- [writeFile (0.6.0)](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#writefilepathstring-contentstring--array-encodingstring-appendbooleanpromise)
601-
- [appendFile (0.6.0) ](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#appendfilepathstring-contentstring--array-encodingstringpromise)
601+
- [appendFile (0.6.0) ](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#appendfilepathstring-contentstring--arraynumber-encodingstring-promisenumber)
602602
- [readFile (0.6.0)](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#readfilepath-encodingpromise)
603-
- [readStream](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#readstreampath-encoding-buffersizepromise)
604-
- [writeStream](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#writestreampathstring-encodingstring-appendbooleanpromise)
603+
- [readStream](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#readstreampath-encoding-buffersize-interval-promisernfbreadstream)
604+
- [hash (0.10.9)](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#hashpath-algorithm-promise)
605+
- [writeStream](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#writestreampathstring-encodingstringpromise)
606+
- [hash](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#hashpath-algorithmpromise)
605607
- [unlink](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#unlinkpathstringpromise)
606608
- [mkdir](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#mkdirpathstringpromise)
607609
- [ls](https://github.com/wkh237/react-native-fetch-blob/wiki/File-System-Access-API#lspathstringpromise)
@@ -651,6 +653,45 @@ RNFetchBlob.fs.readStream(
651653

652654
When using `writeStream`, the stream object becomes writable, and you can then perform operations like `write` and `close`.
653655

656+
Since version 0.10.9 `write()` resolves with the `RNFetchBlob` instance so you can promise-chain write calls:
657+
658+
```js
659+
RNFetchBlob.fs.writeStream(
660+
PATH_TO_FILE,
661+
// encoding, should be one of `base64`, `utf8`, `ascii`
662+
'utf8',
663+
// should data append to existing content ?
664+
true
665+
)
666+
.then(ofstream => ofstream.write('foo'))
667+
.then(ofstream => ofstream.write('bar'))
668+
.then(ofstream => ofstream.write('foobar'))
669+
.then(ofstream => ofstream.close())
670+
.catch(console.error)
671+
```
672+
673+
or
674+
675+
```js
676+
RNFetchBlob.fs.writeStream(
677+
PATH_TO_FILE,
678+
// encoding, should be one of `base64`, `utf8`, `ascii`
679+
'utf8',
680+
// should data append to existing content ?
681+
true
682+
)
683+
.then(stream => Promise.all([
684+
stream.write('foo'),
685+
stream.write('bar'),
686+
stream.write('foobar')
687+
]))
688+
// Use array destructuring to get the stream object from the first item of the array we get from Promise.all()
689+
.then(([stream]) => stream.close())
690+
.catch(console.error)
691+
```
692+
693+
You should **NOT** do something like this:
694+
654695
```js
655696
RNFetchBlob.fs.writeStream(
656697
PATH_TO_FILE,
@@ -659,13 +700,18 @@ RNFetchBlob.fs.writeStream(
659700
// should data append to existing content ?
660701
true)
661702
.then((ofstream) => {
703+
// BAD IDEA - Don't do this, those writes are unchecked:
662704
ofstream.write('foo')
663705
ofstream.write('bar')
664706
ofstream.close()
665707
})
666-
708+
.catch(console.error) // Cannot catch any write() errors!
667709
```
668710

711+
The problem with the above code is that the promises from the `ofstream.write()` calls are detached and "Lost".
712+
That means the entire promise chain A) resolves without waiting for the writes to finish and B) any errors caused by them are lost.
713+
That code may _seem_ to work if there are no errors, but those writes are of the type "fire and forget": You start them and then turn away and never know if they really succeeded.
714+
669715
### Cache File Management
670716

671717
When using `fileCache` or `path` options along with `fetch` API, response data will automatically store into the file system. The files will **NOT** removed unless you `unlink` it. There're several ways to remove the files

android.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const RNFetchBlob:RNFetchBlobNative = NativeModules.RNFetchBlob
1313

1414
/**
1515
* Send an intent to open the file.
16-
* @param {string]} path Path of the file to be open.
16+
* @param {string} path Path of the file to be open.
1717
* @param {string} mime MIME type string
1818
* @return {Promise}
1919
*/

android/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ android {
3434

3535
dependencies {
3636
compile 'com.facebook.react:react-native:+'
37+
//compile 'com.squareup.okhttp3:okhttp:+'
3738
//{RNFetchBlob_PRE_0.28_DEPDENDENCY}
3839
}

android/gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#Wed May 18 12:33:41 CST 2016
1+
#Sat Aug 12 07:48:35 CEST 2017
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME

android/src/main/java/com/RNFetchBlob/RNFetchBlob.java

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import android.app.DownloadManager;
55
import android.content.Intent;
66
import android.net.Uri;
7+
import android.util.SparseArray;
78

89
import com.facebook.react.bridge.ActivityEventListener;
910
import com.facebook.react.bridge.Callback;
@@ -34,26 +35,23 @@
3435

3536
public class RNFetchBlob extends ReactContextBaseJavaModule {
3637

37-
// Cookies
38-
private final ForwardingCookieHandler mCookieHandler;
39-
private final CookieJarContainer mCookieJarContainer;
4038
private final OkHttpClient mClient;
4139

4240
static ReactApplicationContext RCTContext;
43-
static LinkedBlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();
44-
static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 5000, TimeUnit.MILLISECONDS, taskQueue);
41+
private static LinkedBlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();
42+
private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 5000, TimeUnit.MILLISECONDS, taskQueue);
4543
static LinkedBlockingQueue<Runnable> fsTaskQueue = new LinkedBlockingQueue<>();
46-
static ThreadPoolExecutor fsThreadPool = new ThreadPoolExecutor(2, 10, 5000, TimeUnit.MILLISECONDS, taskQueue);
47-
static public boolean ActionViewVisible = false;
48-
static HashMap<Integer, Promise> promiseTable = new HashMap<>();
44+
private static ThreadPoolExecutor fsThreadPool = new ThreadPoolExecutor(2, 10, 5000, TimeUnit.MILLISECONDS, taskQueue);
45+
private static boolean ActionViewVisible = false;
46+
private static SparseArray<Promise> promiseTable = new SparseArray<>();
4947

5048
public RNFetchBlob(ReactApplicationContext reactContext) {
5149

5250
super(reactContext);
5351

5452
mClient = OkHttpClientProvider.getOkHttpClient();
55-
mCookieHandler = new ForwardingCookieHandler(reactContext);
56-
mCookieJarContainer = (CookieJarContainer) mClient.cookieJar();
53+
ForwardingCookieHandler mCookieHandler = new ForwardingCookieHandler(reactContext);
54+
CookieJarContainer mCookieJarContainer = (CookieJarContainer) mClient.cookieJar();
5755
mCookieJarContainer.setCookieJar(new JavaNetCookieJar(mCookieHandler));
5856

5957
RCTContext = reactContext;
@@ -85,11 +83,21 @@ public Map<String, Object> getConstants() {
8583
}
8684

8785
@ReactMethod
88-
public void createFile(final String path, final String content, final String encode, final Callback callback) {
86+
public void createFile(final String path, final String content, final String encode, final Promise promise) {
8987
threadPool.execute(new Runnable() {
9088
@Override
9189
public void run() {
92-
RNFetchBlobFS.createFile(path, content, encode, callback);
90+
RNFetchBlobFS.createFile(path, content, encode, promise);
91+
}
92+
});
93+
}
94+
95+
@ReactMethod
96+
public void createFileASCII(final String path, final ReadableArray dataArray, final Promise promise) {
97+
threadPool.execute(new Runnable() {
98+
@Override
99+
public void run() {
100+
RNFetchBlobFS.createFileASCII(path, dataArray, promise);
93101
}
94102
});
95103

@@ -124,21 +132,10 @@ public void onHostDestroy() {
124132
};
125133
RCTContext.addLifecycleEventListener(listener);
126134
} catch(Exception ex) {
127-
promise.reject(ex.getLocalizedMessage());
135+
promise.reject("EUNSPECIFIED", ex.getLocalizedMessage());
128136
}
129137
}
130138

131-
@ReactMethod
132-
public void createFileASCII(final String path, final ReadableArray dataArray, final Callback callback) {
133-
threadPool.execute(new Runnable() {
134-
@Override
135-
public void run() {
136-
RNFetchBlobFS.createFileASCII(path, dataArray, callback);
137-
}
138-
});
139-
140-
}
141-
142139
@ReactMethod
143140
public void writeArrayChunk(final String streamId, final ReadableArray dataArray, final Callback callback) {
144141
RNFetchBlobFS.writeArrayChunk(streamId, dataArray, callback);
@@ -150,8 +147,8 @@ public void unlink(String path, Callback callback) {
150147
}
151148

152149
@ReactMethod
153-
public void mkdir(String path, Callback callback) {
154-
RNFetchBlobFS.mkdir(path, callback);
150+
public void mkdir(String path, Promise promise) {
151+
RNFetchBlobFS.mkdir(path, promise);
155152
}
156153

157154
@ReactMethod
@@ -176,8 +173,8 @@ public void mv(String path, String dest, Callback callback) {
176173
}
177174

178175
@ReactMethod
179-
public void ls(String path, Callback callback) {
180-
RNFetchBlobFS.ls(path, callback);
176+
public void ls(String path, Promise promise) {
177+
RNFetchBlobFS.ls(path, promise);
181178
}
182179

183180
@ReactMethod
@@ -267,11 +264,21 @@ public void run() {
267264
}
268265

269266
@ReactMethod
267+
public void hash(final String path, final String algorithm, final Promise promise) {
268+
threadPool.execute(new Runnable() {
269+
@Override
270+
public void run() {
271+
RNFetchBlobFS.hash(path, algorithm, promise);
272+
}
273+
});
274+
}
275+
270276
/**
271277
* @param path Stream file path
272278
* @param encoding Stream encoding, should be one of `base64`, `ascii`, and `utf8`
273279
* @param bufferSize Stream buffer size, default to 4096 or 4095(base64).
274280
*/
281+
@ReactMethod
275282
public void readStream(final String path, final String encoding, final int bufferSize, final int tick, final String streamId) {
276283
final ReactApplicationContext ctx = this.getReactApplicationContext();
277284
fsThreadPool.execute(new Runnable() {
@@ -345,10 +352,10 @@ public void getContentIntent(String mime, Promise promise) {
345352

346353
@ReactMethod
347354
public void addCompleteDownload (ReadableMap config, Promise promise) {
348-
DownloadManager dm = (DownloadManager) RNFetchBlob.RCTContext.getSystemService(RNFetchBlob.RCTContext.DOWNLOAD_SERVICE);
355+
DownloadManager dm = (DownloadManager) RCTContext.getSystemService(RCTContext.DOWNLOAD_SERVICE);
349356
String path = RNFetchBlobFS.normalizePath(config.getString("path"));
350357
if(path == null) {
351-
promise.reject("RNFetchblob.addCompleteDownload can not resolve URI:" + config.getString("path"), "RNFetchblob.addCompleteDownload can not resolve URI:" + path);
358+
promise.reject("EINVAL", "RNFetchblob.addCompleteDownload can not resolve URI:" + config.getString("path"));
352359
return;
353360
}
354361
try {
@@ -365,7 +372,7 @@ public void addCompleteDownload (ReadableMap config, Promise promise) {
365372
promise.resolve(null);
366373
}
367374
catch(Exception ex) {
368-
promise.reject("RNFetchblob.addCompleteDownload failed", ex.getStackTrace().toString());
375+
promise.reject("EUNSPECIFIED", ex.getLocalizedMessage());
369376
}
370377

371378
}

0 commit comments

Comments
 (0)