From d807f0f4affcdeb0b9d62e66a6a110474a69f105 Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Sun, 11 Jun 2017 16:26:38 +0800 Subject: [PATCH 1/6] Add missing Android implementation --- android.js | 14 +++++++++++--- .../main/java/com/RNFetchBlob/RNFetchBlobFS.java | 12 ++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/android.js b/android.js index e39d52d32..0b5dbd84b 100644 --- a/android.js +++ b/android.js @@ -21,18 +21,26 @@ function actionViewIntent(path:string, mime:string = 'text/plain') { if(Platform.OS === 'android') return RNFetchBlob.actionViewIntent(path, mime) else - return Promise.reject('RNFetchBlob.actionViewIntent only supports Android.') + return Promise.reject('RNFetchBlob.android.actionViewIntent only supports Android.') } function getContentIntent(mime:string) { if(Platform.OS === 'android') return RNFetchBlob.getContentIntent(mime) else - return Promise.reject('RNFetchBlob.getContentIntent only supports Android.') + return Promise.reject('RNFetchBlob.android.getContentIntent only supports Android.') +} + +function addCompleteDownload(config) { + if(Platform.OS === 'android') + return RNFetchBlob.addCompleteDownload(config) + else + return Promise.reject('RNFetchBlob.android.addCompleteDownload only supports Android.') } export default { actionViewIntent, - getContentIntent + getContentIntent, + addCompleteDownload } diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java index def758e05..7b5e3bd11 100644 --- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java +++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java @@ -882,13 +882,21 @@ static boolean isAsset(String path) { return false; } + /** + * Normalize the path, remove URI scheme (xxx://) so that we can handle it. + * @param path URI string. + * @return Normalized string + */ static String normalizePath(String path) { if(path == null) return null; - Uri uri = Uri.parse(path); - if(uri.getScheme() == null) { + if(!path.matches("\\w+\\:.*")) return path; + if(path.startsWith("file://")) { + return path.replace("file://", ""); } + + Uri uri = Uri.parse(path); if(path.startsWith(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET)) { return path; } From 5b43136bebaba47cb329b7c65e2d4b4472dccedb Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Sun, 11 Jun 2017 16:27:08 +0800 Subject: [PATCH 2/6] Fix Fetch Replacement progress and cancel task issue #370 --- .../java/com/RNFetchBlob/RNFetchBlob.java | 28 +++++++++++++ polyfill/Fetch.js | 42 ++++++++++++------- 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlob.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlob.java index d046f1804..38a814ebc 100644 --- a/android/src/main/java/com/RNFetchBlob/RNFetchBlob.java +++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlob.java @@ -1,6 +1,7 @@ package com.RNFetchBlob; import android.app.Activity; +import android.app.DownloadManager; import android.content.Intent; import android.net.Uri; @@ -341,4 +342,31 @@ public void getContentIntent(String mime, Promise promise) { } + @ReactMethod + public void addCompleteDownload (ReadableMap config, Promise promise) { + DownloadManager dm = (DownloadManager) RNFetchBlob.RCTContext.getSystemService(RNFetchBlob.RCTContext.DOWNLOAD_SERVICE); + String path = RNFetchBlobFS.normalizePath(config.getString("path")); + if(path == null) { + promise.reject("RNFetchblob.addCompleteDownload can not resolve URI:" + config.getString("path"), "RNFetchblob.addCompleteDownload can not resolve URI:" + path); + return; + } + try { + WritableMap stat = RNFetchBlobFS.statFile(path); + dm.addCompletedDownload( + config.hasKey("title") ? config.getString("title") : "", + config.hasKey("description") ? config.getString("description") : "", + true, + config.hasKey("mime") ? config.getString("mime") : null, + path, + Long.valueOf(stat.getString("size")), + config.hasKey("showNotification") && config.getBoolean("showNotification") + ); + promise.resolve(null); + } + catch(Exception ex) { + promise.reject("RNFetchblob.addCompleteDownload failed", ex.getStackTrace().toString()); + } + + } + } diff --git a/polyfill/Fetch.js b/polyfill/Fetch.js index 7907f8f17..7be52e084 100644 --- a/polyfill/Fetch.js +++ b/polyfill/Fetch.js @@ -57,24 +57,38 @@ class RNFetchBlobFetchPolyfill { // task is a progress reportable and cancellable Promise, however, // task.then is not, so we have to extend task.then with progress and // cancel function - let task = promise + let progressHandler, uploadHandler, cancelHandler + let statefulPromise = promise .then((body) => { - return RNFetchBlob.config(config) - .fetch(options.method, url, options.headers, body) + let task = RNFetchBlob.config(config) + .fetch(options.method, url, options.headers, body) + if(progressHandler) + task.progress(progressHandler) + if(uploadHandler) + task.uploadProgress(uploadHandler) + if(cancelHandler) + task.cancel() + return task.then((resp) => { + log.verbose('response', resp) + // release blob cache created when sending request + if(blobCache !== null && blobCache instanceof Blob) + blobCache.close() + return Promise.resolve(new RNFetchBlobFetchRepsonse(resp)) + }) }) - let statefulPromise = task.then((resp) => { - log.verbose('response', resp) - // release blob cache created when sending request - if(blobCache !== null && blobCache instanceof Blob) - blobCache.close() - return Promise.resolve(new RNFetchBlobFetchRepsonse(resp)) - }) - // extend task.then progress with report and cancelling functions - statefulPromise.cancel = task.cancel - statefulPromise.progress = task.progress - statefulPromise.uploadProgress = task.uploadProgress + statefulPromise.progress = (fn) => { + progressHandler = fn + } + statefulPromise.uploadProgress = (fn) => { + uploadHandler = fn + } + statefulPromise.cancel = () => { + cancelHandler = true + if(task.cancel) + task.cancel() + } return statefulPromise From d00bd9138a483d00c1fe45c3b0f02dda19ff4a62 Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Wed, 14 Jun 2017 22:39:34 +0800 Subject: [PATCH 3/6] Fix missing Android import --- android/src/main/java/com/RNFetchBlob/RNFetchBlob.java | 1 + 1 file changed, 1 insertion(+) diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlob.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlob.java index 38a814ebc..19e1be435 100644 --- a/android/src/main/java/com/RNFetchBlob/RNFetchBlob.java +++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlob.java @@ -16,6 +16,7 @@ import com.facebook.react.bridge.ReadableMap; // Cookies +import com.facebook.react.bridge.WritableMap; import com.facebook.react.modules.network.ForwardingCookieHandler; import com.facebook.react.modules.network.CookieJarContainer; import com.facebook.react.modules.network.OkHttpClientProvider; From 4073093f487ded69b197b88b107d6a95b141780c Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Wed, 14 Jun 2017 22:39:34 +0800 Subject: [PATCH 4/6] Fix missing Android import fix --- android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java index f01e82efb..db213c1e8 100644 --- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java +++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java @@ -192,7 +192,7 @@ else if(this.options.fileCache) try { // use trusty SSL socket if (this.options.trusty) { - clientBuilder = RNFetchBlobUtils.getUnsafeOkHttpClient(); + clientBuilder = RNFetchBlobUtils.getUnsafeOkHttpClient(client); } else { clientBuilder = client.newBuilder(); } From 1d4e69cf20f0d86166b8f1346981874873b9847a Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Tue, 20 Jun 2017 23:12:58 +0800 Subject: [PATCH 5/6] Fix incorrect UTF-8 data conversion issue when the data contains special characters. --- android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java index 7b5e3bd11..1537bca71 100644 --- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java +++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java @@ -250,10 +250,7 @@ public void readStream(String path, String encoding, int bufferSize, int tick, f CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder(); while ((cursor = fs.read(buffer)) != -1) { encoder.encode(ByteBuffer.wrap(buffer).asCharBuffer()); - String chunk = new String(buffer); - if(cursor != bufferSize) { - chunk = chunk.substring(0, cursor); - } + String chunk = new String(buffer, 0, cursor); emitStreamEvent(streamId, "data", chunk); if(tick > 0) SystemClock.sleep(tick); From 2c16a9488d4b883c4086ad68f61aada32c8a2095 Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Mon, 26 Jun 2017 23:32:48 +0800 Subject: [PATCH 6/6] Fix IOS request timeout issue #368 by change default request setting to defaultSessionConfiguration, and make backgroundSessionConfigurationWithIdentifier optional --- ios/RNFetchBlobNetwork.m | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/ios/RNFetchBlobNetwork.m b/ios/RNFetchBlobNetwork.m index 85030b743..7be57fc59 100644 --- a/ios/RNFetchBlobNetwork.m +++ b/ios/RNFetchBlobNetwork.m @@ -82,6 +82,7 @@ @interface RNFetchBlobNetwork () NSMutableArray * redirects; ResponseFormat responseFormat; BOOL * followRedirect; + BOOL backgroundTask; } @end @@ -168,6 +169,8 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options self.expectedBytes = 0; self.receivedBytes = 0; self.options = options; + + backgroundTask = [options valueForKey:@"IOSBackgroundTask"] == nil ? NO : [[options valueForKey:@"IOSBackgroundTask"] boolValue]; followRedirect = [options valueForKey:@"followRedirect"] == nil ? YES : [[options valueForKey:@"followRedirect"] boolValue]; isIncrement = [options valueForKey:@"increment"] == nil ? NO : [[options valueForKey:@"increment"] boolValue]; redirects = [[NSMutableArray alloc] init]; @@ -192,13 +195,12 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options // the session trust any SSL certification NSURLSessionConfiguration *defaultConfigObject; - if(!followRedirect) - { - defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration]; - } - else + + defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration]; + + if(backgroundTask) { - NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:taskId]; + defaultConfigObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:taskId]; } // set request timeout @@ -247,14 +249,6 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; __block UIApplication * app = [UIApplication sharedApplication]; - // #115 handling task expired when application entering backgound for a long time - UIBackgroundTaskIdentifier tid = [app beginBackgroundTaskWithName:taskId expirationHandler:^{ - NSLog([NSString stringWithFormat:@"session %@ expired", taskId ]); - [expirationTable setObject:task forKey:taskId]; - // comment out this one as it might cause app crash #271 -// [app endBackgroundTask:tid]; - }]; - } // #115 Invoke fetch.expire event on those expired requests so that the expired event can be handled