浏览代码

Merge branch '0.10.5' into issue-287-wip

Ben Hsieh 7 年前
父节点
当前提交
4d15c0f3ed

+ 6
- 1
README.md 查看文件

@@ -3,7 +3,6 @@
3 3
 
4 4
 
5 5
 A project committed to making file access and data transfer easier, efficient for React Native developers.
6
-
7 6
 > For Firebase Storage solution, please upgrade to latest version for best compatibility.
8 7
 
9 8
 ## Features
@@ -61,6 +60,12 @@ pod 'react-native-fetch-blob',
61 60
     :path => '../node_modules/react-native-fetch-blob'
62 61
 ```
63 62
 
63
+After `0.10.3` you can install this package directly from Github 
64
+
65
+```sh
66
+# replace <branch_name> with any one of the branches
67
+npm install --save github:wkh237/react-native-fetch-blob-package#<branch_name>
68
+```
64 69
 **Automatically Link Native Modules**
65 70
 
66 71
 For 0.29.2+ projects, simply link native packages via the following command because rnpm has been merged into react-native, you no longer need it.

+ 9
- 1
android.js 查看文件

@@ -24,7 +24,15 @@ function actionViewIntent(path:string, mime:string = 'text/plain') {
24 24
     return Promise.reject('RNFetchBlob.actionViewIntent only supports Android.')
25 25
 }
26 26
 
27
+function getContentIntent(mime:string) {
28
+  if(Platform.OS === 'android')
29
+    return RNFetchBlob.getContentIntent(mime)
30
+  else
31
+    return Promise.reject('RNFetchBlob.getContentIntent only supports Android.')
32
+}
33
+
27 34
 
28 35
 export default {
29
-  actionViewIntent
36
+  actionViewIntent,
37
+  getContentIntent
30 38
 }

+ 36
- 0
android/src/main/java/com/RNFetchBlob/RNFetchBlob.java 查看文件

@@ -1,9 +1,12 @@
1 1
 package com.RNFetchBlob;
2 2
 
3
+import android.app.Activity;
3 4
 import android.content.Intent;
4 5
 import android.net.Uri;
6
+import android.util.Log;
5 7
 
6 8
 import com.RNFetchBlob.Utils.RNFBCookieJar;
9
+import com.facebook.react.bridge.ActivityEventListener;
7 10
 import com.facebook.react.bridge.Callback;
8 11
 import com.facebook.react.bridge.LifecycleEventListener;
9 12
 import com.facebook.react.bridge.Promise;
@@ -15,11 +18,16 @@ import com.facebook.react.bridge.ReadableMap;
15 18
 import com.facebook.react.bridge.WritableArray;
16 19
 import com.facebook.react.bridge.WritableMap;
17 20
 
21
+import java.util.HashMap;
18 22
 import java.util.Map;
23
+import java.util.UUID;
19 24
 import java.util.concurrent.LinkedBlockingQueue;
20 25
 import java.util.concurrent.ThreadPoolExecutor;
21 26
 import java.util.concurrent.TimeUnit;
22 27
 
28
+import static android.app.Activity.RESULT_OK;
29
+import static com.RNFetchBlob.RNFetchBlobConst.GET_CONTENT_INTENT;
30
+
23 31
 public class RNFetchBlob extends ReactContextBaseJavaModule {
24 32
 
25 33
     static ReactApplicationContext RCTContext;
@@ -28,12 +36,28 @@ public class RNFetchBlob extends ReactContextBaseJavaModule {
28 36
     static LinkedBlockingQueue<Runnable> fsTaskQueue = new LinkedBlockingQueue<>();
29 37
     static ThreadPoolExecutor fsThreadPool = new ThreadPoolExecutor(2, 10, 5000, TimeUnit.MILLISECONDS, taskQueue);
30 38
     static public boolean ActionViewVisible = false;
39
+    static HashMap<Integer, Promise> promiseTable = new HashMap<>();
31 40
 
32 41
     public RNFetchBlob(ReactApplicationContext reactContext) {
33 42
 
34 43
         super(reactContext);
35 44
 
36 45
         RCTContext = reactContext;
46
+        reactContext.addActivityEventListener(new ActivityEventListener() {
47
+            @Override
48
+            public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
49
+                if(requestCode == GET_CONTENT_INTENT && resultCode == RESULT_OK) {
50
+                    Uri d = data.getData();
51
+                    promiseTable.get(GET_CONTENT_INTENT).resolve(d.toString());
52
+                    promiseTable.remove(GET_CONTENT_INTENT);
53
+                }
54
+            }
55
+
56
+            @Override
57
+            public void onNewIntent(Intent intent) {
58
+
59
+            }
60
+        });
37 61
     }
38 62
 
39 63
     @Override
@@ -322,4 +346,16 @@ public class RNFetchBlob extends ReactContextBaseJavaModule {
322 346
         new RNFetchBlobReq(options, taskId, method, url, headers, null, body, callback).run();
323 347
     }
324 348
 
349
+    @ReactMethod
350
+    public void getContentIntent(String mime, Promise promise) {
351
+        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
352
+        if(mime != null)
353
+            i.setType(mime);
354
+        else
355
+            i.setType("*/*");
356
+        promiseTable.put(GET_CONTENT_INTENT, promise);
357
+        this.getReactApplicationContext().startActivityForResult(i, GET_CONTENT_INTENT, null);
358
+
359
+    }
360
+
325 361
 }

+ 1
- 0
android/src/main/java/com/RNFetchBlob/RNFetchBlobConst.java 查看文件

@@ -13,5 +13,6 @@ public class RNFetchBlobConst {
13 13
     public static final String RNFB_RESPONSE_BASE64 = "base64";
14 14
     public static final String RNFB_RESPONSE_UTF8  = "utf8";
15 15
     public static final String RNFB_RESPONSE_PATH  = "path";
16
+    public static final Integer GET_CONTENT_INTENT = 99900;
16 17
 
17 18
 }

+ 4
- 2
android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java 查看文件

@@ -265,8 +265,9 @@ public class RNFetchBlobFS {
265 265
                 while ((cursor = fs.read(buffer)) != -1) {
266 266
                     encoder.encode(ByteBuffer.wrap(buffer).asCharBuffer());
267 267
                     String chunk = new String(buffer);
268
-                    if(cursor != bufferSize)
268
+                    if(cursor != bufferSize) {
269 269
                         chunk = chunk.substring(0, cursor);
270
+                    }
270 271
                     emitStreamEvent(streamId, "data", chunk);
271 272
                     if(tick > 0)
272 273
                         SystemClock.sleep(tick);
@@ -308,7 +309,8 @@ public class RNFetchBlobFS {
308 309
             buffer = null;
309 310
 
310 311
         } catch (Exception err) {
311
-            emitStreamEvent(streamId, "error", "Failed to convert data to "+encoding+" encoded string, this might due to the source data is not able to convert using this encoding.");
312
+            emitStreamEvent(streamId, "warn", "Failed to convert data to "+encoding+" encoded string, this might due to the source data is not able to convert using this encoding.");
313
+            err.printStackTrace();
312 314
         }
313 315
     }
314 316
 

+ 10
- 30
android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java 查看文件

@@ -220,8 +220,8 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
220 220
                             responseFormat = ResponseFormat.UTF8;
221 221
                     }
222 222
                     else {
223
-                        builder.header(key, value);
224
-                        mheaders.put(key, value);
223
+                        builder.header(key.toLowerCase(), value);
224
+                        mheaders.put(key.toLowerCase(), value);
225 225
                     }
226 226
                 }
227 227
             }
@@ -304,9 +304,9 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
304 304
             clientBuilder.addNetworkInterceptor(new Interceptor() {
305 305
                 @Override
306 306
                 public Response intercept(Chain chain) throws IOException {
307
-                        redirects.add(chain.request().url().toString());
308
-                        return chain.proceed(chain.request());
309
-                    }
307
+                    redirects.add(chain.request().url().toString());
308
+                    return chain.proceed(chain.request());
309
+                }
310 310
             });
311 311
             // Add request interceptor for upload progress event
312 312
             clientBuilder.addInterceptor(new Interceptor() {
@@ -500,32 +500,11 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
500 500
                     // It uses customized response body which is able to report download progress
501 501
                     // and write response data to destination path.
502 502
                     resp.body().bytes();
503
-
504 503
                 } catch (Exception ignored) {
505 504
 //                    ignored.printStackTrace();
506 505
                 }
507 506
                 this.destPath = this.destPath.replace("?append=true", "");
508
-
509
-                try {
510
-                    long expectedLength = resp.body().contentLength();
511
-                    // when response contains Content-Length, check if the stream length is correct
512
-                    if(expectedLength > 0) {
513
-                        long actualLength = new File(this.destPath).length();
514
-                        if(actualLength != expectedLength) {
515
-                            callback.invoke("RNFetchBlob failed to write data to storage : expected " + expectedLength + " bytes but got " + actualLength + " bytes", null);
516
-                        }
517
-                        else {
518
-                            callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, this.destPath);
519
-                        }
520
-                    }
521
-                    else {
522
-                        callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, this.destPath);
523
-                    }
524
-                }
525
-                catch (Exception err) {
526
-                    callback.invoke(err.getMessage());
527
-                    err.printStackTrace();
528
-                }
507
+                callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, this.destPath);
529 508
                 break;
530 509
             default:
531 510
                 try {
@@ -536,7 +515,7 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
536 515
                 break;
537 516
         }
538 517
 //        if(!resp.isSuccessful())
539
-            resp.body().close();
518
+        resp.body().close();
540 519
         releaseTaskResource();
541 520
     }
542 521
 
@@ -578,7 +557,7 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
578 557
         }
579 558
         WritableArray redirectList = Arguments.createArray();
580 559
         for(String r : redirects) {
581
-                redirectList.pushString(r);
560
+            redirectList.pushString(r);
582 561
         }
583 562
         info.putArray("redirects", redirectList);
584 563
         info.putMap("headers", headers);
@@ -629,7 +608,8 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
629 608
     private String getHeaderIgnoreCases(HashMap<String,String> headers, String field) {
630 609
         String val = headers.get(field);
631 610
         if(val != null) return val;
632
-        return headers.get(field.toLowerCase()) == null ? "" : headers.get(field.toLowerCase());
611
+        String lowerCasedValue = headers.get(field.toLowerCase());
612
+        return lowerCasedValue == null ? "" : lowerCasedValue;
633 613
     }
634 614
 
635 615
     private void emitStateEvent(WritableMap args) {

+ 4
- 3
index.js 查看文件

@@ -220,9 +220,10 @@ function fetch(...args:any):Promise {
220 220
 
221 221
   // # 241 normalize null or undefined headers, in case nil or null string
222 222
   // pass to native context
223
-  _.each(headers, (h,i) =>  {
224
-    headers[i] = h || ''
225
-  });
223
+  headers = _.reduce(headers, (result, value, key) => {
224
+    result[key] = value || ''
225
+    return result
226
+  }, {});
226 227
 
227 228
   // fetch from file system
228 229
   if(URIUtil.isFileURI(url)) {

+ 55
- 8
ios/RNFetchBlob/RNFetchBlob.m 查看文件

@@ -80,10 +80,25 @@ RCT_EXPORT_METHOD(fetchBlobForm:(NSDictionary *)options
80 80
                   callback:(RCTResponseSenderBlock)callback)
81 81
 {
82 82
 
83
-    [RNFetchBlobReqBuilder buildMultipartRequest:options taskId:taskId method:method url:url headers:headers form:form onComplete:^(__weak NSURLRequest *req, long bodyLength) {
83
+    [RNFetchBlobReqBuilder buildMultipartRequest:options
84
+                                          taskId:taskId
85
+                                          method:method
86
+                                             url:url
87
+                                         headers:headers
88
+                                            form:form
89
+                                      onComplete:^(__weak NSURLRequest *req, long bodyLength)
90
+    {
91
+        // something went wrong when building the request body
92
+        if(req == nil)
93
+        {
94
+            callback(@[@"RNFetchBlob.fetchBlobForm failed to create request body"]);
95
+        }
84 96
         // send HTTP request
85
-        RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init];
86
-        [utils sendRequest:options contentLength:bodyLength bridge:self.bridge taskId:taskId withRequest:req callback:callback];
97
+        else
98
+        {
99
+            RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init];
100
+            [utils sendRequest:options contentLength:bodyLength bridge:self.bridge taskId:taskId withRequest:req callback:callback];
101
+        }
87 102
     }];
88 103
 
89 104
 }
@@ -97,10 +112,25 @@ RCT_EXPORT_METHOD(fetchBlob:(NSDictionary *)options
97 112
                   headers:(NSDictionary *)headers
98 113
                   body:(NSString *)body callback:(RCTResponseSenderBlock)callback)
99 114
 {
100
-    [RNFetchBlobReqBuilder buildOctetRequest:options taskId:taskId method:method url:url headers:headers body:body onComplete:^(NSURLRequest *req, long bodyLength) {
115
+    [RNFetchBlobReqBuilder buildOctetRequest:options
116
+                                      taskId:taskId
117
+                                      method:method
118
+                                         url:url
119
+                                     headers:headers
120
+                                        body:body
121
+                                  onComplete:^(NSURLRequest *req, long bodyLength)
122
+    {
123
+        // something went wrong when building the request body
124
+        if(req == nil)
125
+        {
126
+            callback(@[@"RNFetchBlob.fetchBlob failed to create request body"]);
127
+        }
101 128
         // send HTTP request
102
-        __block RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init];
103
-        [utils sendRequest:options contentLength:bodyLength bridge:self.bridge taskId:taskId withRequest:req callback:callback];
129
+        else
130
+        {
131
+            __block RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init];
132
+            [utils sendRequest:options contentLength:bodyLength bridge:self.bridge taskId:taskId withRequest:req callback:callback];
133
+        }
104 134
     }];
105 135
 }
106 136
 
@@ -394,10 +424,27 @@ RCT_EXPORT_METHOD(mkdir:(NSString *)path callback:(RCTResponseSenderBlock) callb
394 424
 }
395 425
 
396 426
 #pragma mark - fs.readFile
397
-RCT_EXPORT_METHOD(readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
427
+RCT_EXPORT_METHOD(readFile:(NSString *)path
428
+                  encoding:(NSString *)encoding
429
+                  resolver:(RCTPromiseResolveBlock)resolve
430
+                  rejecter:(RCTPromiseRejectBlock)reject)
398 431
 {
399 432
 
400
-    [RNFetchBlobFS readFile:path encoding:encoding resolver:resolve rejecter:reject onComplete:nil];
433
+    [RNFetchBlobFS readFile:path encoding:encoding onComplete:^(id content, NSString * err) {
434
+        if(err != nil)
435
+        {
436
+            reject(@"RNFetchBlob failed to read file", err, nil);
437
+            return;
438
+        }
439
+        if(encoding == @"ascii")
440
+        {
441
+            resolve((NSMutableArray *)content);
442
+        }
443
+        else
444
+        {
445
+            resolve((NSString *)content);
446
+        }
447
+    }];
401 448
 }
402 449
 
403 450
 #pragma mark - fs.readStream

+ 1
- 1
ios/RNFetchBlobFS.h 查看文件

@@ -61,7 +61,7 @@
61 61
 + (void) exists:(NSString *) path callback:(RCTResponseSenderBlock)callback;
62 62
 + (void) writeFileArray:(NSString *)path data:(NSArray *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
63 63
 + (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
64
-+ (void) readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject onComplete:(void (^)(NSData * content))onComplete;
64
++ (void) readFile:(NSString *)path encoding:(NSString *)encoding onComplete:(void (^)(NSData * content, NSString * errMsg))onComplete;
65 65
 + (void) readAssetFile:(NSData *)assetUrl completionBlock:(void(^)(NSData * content))completionBlock failBlock:(void(^)(NSError * err))failBlock;
66 66
 + (void) slice:(NSString *)path
67 67
          dest:(NSString *)dest

+ 49
- 57
ios/RNFetchBlobFS.m 查看文件

@@ -418,54 +418,49 @@ NSMutableDictionary *fileStreams = nil;
418 418
 
419 419
 # pragma mark - read file
420 420
 
421
-+ (void) readFile:(NSString *)path encoding:(NSString *)encoding
422
-         resolver:(RCTPromiseResolveBlock)resolve
423
-         rejecter:(RCTPromiseRejectBlock)reject
424
-       onComplete:(void (^)(NSData * content))onComplete
421
++ (void) readFile:(NSString *)path
422
+         encoding:(NSString *)encoding
423
+       onComplete:(void (^)(id content, NSString * errMsg))onComplete
425 424
 {
426
-    @try
427
-    {
428
-        [[self class] getPathFromUri:path completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
429
-            __block NSData * fileContent;
430
-            NSError * err;
431
-            __block Byte * buffer;
432
-            if(asset != nil)
425
+    [[self class] getPathFromUri:path completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
426
+        __block NSData * fileContent;
427
+        NSError * err;
428
+        __block Byte * buffer;
429
+        if(asset != nil)
430
+        {
431
+            buffer = malloc(asset.size);
432
+            [asset getBytes:buffer fromOffset:0 length:asset.size error:&err];
433
+            if(err != nil)
433 434
             {
434
-                buffer = malloc(asset.size);
435
-                [asset getBytes:buffer fromOffset:0 length:asset.size error:&err];
436
-                if(err != nil)
437
-                {
438
-                    reject(@"RNFetchBlobFS readFile error", @"failed to read asset", [err localizedDescription]);
439
-                    return;
440
-                }
441
-                fileContent = [NSData dataWithBytes:buffer length:asset.size];
435
+                onComplete(nil, [err description]);
442 436
                 free(buffer);
437
+                return;
443 438
             }
444
-            else
445
-            {
446
-                if(![[NSFileManager defaultManager] fileExistsAtPath:path]) {
447
-
448
-                    reject(@"RNFetchBlobFS readFile error", @"file not exists", nil);
449
-                    return;
450
-                }
451
-                fileContent = [NSData dataWithContentsOfFile:path];
452
-
439
+            fileContent = [NSData dataWithBytes:buffer length:asset.size];
440
+            free(buffer);
441
+        }
442
+        else
443
+        {
444
+            if(![[NSFileManager defaultManager] fileExistsAtPath:path]) {
445
+                onComplete(nil, @"file not exists");
446
+                return;
453 447
             }
454
-            if(onComplete != nil)
455
-                onComplete(fileContent);
456
-
457
-            if([[encoding lowercaseString] isEqualToString:@"utf8"]) {
458
-                if(resolve != nil) {
459
-                    NSString * utf8 = [[NSString alloc] initWithData:fileContent encoding:NSUTF8StringEncoding];
460
-                    if(utf8 == nil)
461
-                        resolve([[NSString alloc] initWithData:fileContent encoding:NSISOLatin1StringEncoding]);
462
-                    else
463
-                        resolve(utf8);
464
-                }
448
+            fileContent = [NSData dataWithContentsOfFile:path];
449
+            
450
+        }
451
+        
452
+        if(encoding != nil)
453
+        {
454
+            if([[encoding lowercaseString] isEqualToString:@"utf8"])
455
+            {
456
+                NSString * utf8 = [[NSString alloc] initWithData:fileContent encoding:NSUTF8StringEncoding];
457
+                if(utf8 == nil)
458
+                    onComplete([[NSString alloc] initWithData:fileContent encoding:NSISOLatin1StringEncoding], nil);
459
+                else
460
+                    onComplete(utf8, nil);
465 461
             }
466 462
             else if ([[encoding lowercaseString] isEqualToString:@"base64"]) {
467
-                if(resolve != nil)
468
-                    resolve([fileContent base64EncodedStringWithOptions:0]);
463
+                onComplete([fileContent base64EncodedStringWithOptions:0], nil);
469 464
             }
470 465
             else if ([[encoding lowercaseString] isEqualToString:@"ascii"]) {
471 466
                 NSMutableArray * resultArray = [NSMutableArray array];
@@ -473,18 +468,18 @@ NSMutableDictionary *fileStreams = nil;
473 468
                 for(int i=0;i<[fileContent length];i++) {
474 469
                     [resultArray addObject:[NSNumber numberWithChar:bytes[i]]];
475 470
                 }
476
-                if(resolve != nil)
477
-                    resolve(resultArray);
471
+                onComplete(resultArray, nil);
478 472
             }
479
-        }];
480
-    }
481
-    @catch(NSException * e)
482
-    {
483
-        if(reject != nil)
484
-            reject(@"RNFetchBlobFS readFile error", @"error", [e description]);
485
-    }
473
+        }
474
+        else
475
+        {
476
+            onComplete(fileContent, nil);
477
+        }
478
+        
479
+    }];
486 480
 }
487 481
 
482
+
488 483
 # pragma mark - mkdir
489 484
 
490 485
 + (BOOL) mkdir:(NSString *) path {
@@ -516,7 +511,7 @@ NSMutableDictionary *fileStreams = nil;
516 511
              @"size" : size,
517 512
              @"filename" : filename,
518 513
              @"path" : path,
519
-             @"lastModified" : [NSString stringWithFormat:@"%@", [NSNumber numberWithLong:(time_t) [lastModified timeIntervalSince1970]*1000]],
514
+             @"lastModified" : [NSNumber numberWithLong:(time_t) [lastModified timeIntervalSince1970]*1000],
520 515
              @"type" : isDir ? @"directory" : @"file"
521 516
             };
522 517
 
@@ -753,8 +748,6 @@ NSMutableDictionary *fileStreams = nil;
753 748
 
754 749
 +(void) df:(RCTResponseSenderBlock)callback
755 750
 {
756
-    uint64_t totalSpace = 0;
757
-    uint64_t totalFreeSpace = 0;
758 751
     NSError *error = nil;
759 752
     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
760 753
     NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
@@ -762,11 +755,10 @@ NSMutableDictionary *fileStreams = nil;
762 755
     if (dictionary) {
763 756
         NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];
764 757
         NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
765
-        totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
766
-        totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
758
+        
767 759
         callback(@[[NSNull null], @{
768
-                  @"free" : [NSString stringWithFormat:@"%d", totalFreeSpace],
769
-                  @"total" : [NSString stringWithFormat:@"%d", totalSpace]
760
+                  @"free" : freeFileSystemSizeInBytes,
761
+                  @"total" : fileSystemSizeInBytes,
770 762
                 }]);
771 763
     } else {
772 764
         callback(@[@"failed to get storage usage."]);

+ 0
- 18
ios/RNFetchBlobNetwork.h 查看文件

@@ -23,11 +23,6 @@
23 23
 
24 24
 typedef void(^CompletionHander)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error);
25 25
 typedef void(^DataTaskCompletionHander) (NSData * _Nullable resp, NSURLResponse * _Nullable response, NSError * _Nullable error);
26
-typedef NS_ENUM(NSUInteger, ResponseFormat) {
27
-    UTF8,
28
-    BASE64,
29
-    AUTO
30
-};
31 26
 
32 27
 @interface RNFetchBlobNetwork : NSObject  <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
33 28
 
@@ -43,19 +38,6 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
43 38
 @property (strong, nonatomic) CompletionHander fileTaskCompletionHandler;
44 39
 @property (strong, nonatomic) DataTaskCompletionHander dataTaskCompletionHandler;
45 40
 @property (nullable, nonatomic) NSError * error;
46
-@property (nullable, nonatomic) NSMutableArray * redirects;
47
-
48
-@property (nonatomic) BOOL respFile;
49
-@property (nonatomic) BOOL isNewPart;
50
-@property (nonatomic) BOOL isIncrement;
51
-@property (nullable, nonatomic) NSMutableData * partBuffer;
52
-@property (nullable, nonatomic) NSString * destPath;
53
-@property (nullable, nonatomic) NSOutputStream * writeStream;
54
-@property (nonatomic) long bodyLength;
55
-@property (nullable, nonatomic) NSMutableDictionary * respInfo;
56
-@property (nonatomic) NSInteger respStatus;
57
-@property (nonatomic) ResponseFormat responseFormat;
58
-@property ( nonatomic) BOOL followRedirect;
59 41
 
60 42
 
61 43
 + (NSMutableDictionary  * _Nullable ) normalizeHeaders:(NSDictionary * _Nullable)headers;

+ 26
- 14
ios/RNFetchBlobNetwork.m 查看文件

@@ -61,6 +61,30 @@ static void initialize_tables() {
61 61
 }
62 62
 
63 63
 
64
+typedef NS_ENUM(NSUInteger, ResponseFormat) {
65
+    UTF8,
66
+    BASE64,
67
+    AUTO
68
+};
69
+
70
+
71
+@interface RNFetchBlobNetwork ()
72
+{
73
+    BOOL * respFile;
74
+    BOOL isNewPart;
75
+    BOOL * isIncrement;
76
+    NSMutableData * partBuffer;
77
+    NSString * destPath;
78
+    NSOutputStream * writeStream;
79
+    long bodyLength;
80
+    NSMutableDictionary * respInfo;
81
+    NSInteger respStatus;
82
+    NSMutableArray * redirects;
83
+    ResponseFormat responseFormat;
84
+    BOOL * followRedirect;
85
+}
86
+
87
+@end
64 88
 
65 89
 @implementation RNFetchBlobNetwork
66 90
 
@@ -72,23 +96,10 @@ NSOperationQueue *taskQueue;
72 96
 @synthesize callback;
73 97
 @synthesize bridge;
74 98
 @synthesize options;
75
-@synthesize redirects;
76 99
 @synthesize fileTaskCompletionHandler;
77 100
 @synthesize dataTaskCompletionHandler;
78 101
 @synthesize error;
79 102
 
80
-@synthesize respFile;
81
-@synthesize isNewPart;
82
-@synthesize isIncrement;
83
-@synthesize partBuffer;
84
-@synthesize destPath;
85
-@synthesize writeStream;
86
-@synthesize bodyLength;
87
-@synthesize respInfo;
88
-@synthesize respStatus;
89
-@synthesize responseFormat;
90
-@synthesize followRedirect;
91
-
92 103
 
93 104
 // constructor
94 105
 - (id)init {
@@ -240,7 +251,8 @@ NSOperationQueue *taskQueue;
240 251
     UIBackgroundTaskIdentifier tid = [app beginBackgroundTaskWithName:taskId expirationHandler:^{
241 252
         NSLog([NSString stringWithFormat:@"session %@ expired", taskId ]);
242 253
         [expirationTable setObject:task forKey:taskId];
243
-        [app endBackgroundTask:tid];
254
+        // comment out this one as it might cause app crash #271
255
+//        [app endBackgroundTask:tid];
244 256
     }];
245 257
 
246 258
 }

+ 49
- 26
ios/RNFetchBlobReqBuilder.m 查看文件

@@ -51,21 +51,29 @@
51 51
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
52 52
         __block NSMutableData * postData = [[NSMutableData alloc] init];
53 53
         // combine multipart/form-data body
54
-        [[self class] buildFormBody:form boundary:boundary onComplete:^(NSData *formData) {
55
-            if(formData != nil) {
56
-                [postData appendData:formData];
57
-                // close form data
58
-                [postData appendData: [[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
59
-                [request setHTTPBody:postData];
54
+        [[self class] buildFormBody:form boundary:boundary onComplete:^(NSData *formData, BOOL hasError) {
55
+            if(hasError)
56
+            {
57
+                onComplete(nil, nil);
58
+            }
59
+            else
60
+            {
61
+                if(formData != nil)
62
+                {
63
+                    [postData appendData:formData];
64
+                    // close form data
65
+                    [postData appendData: [[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
66
+                    [request setHTTPBody:postData];
67
+                }
68
+                // set content-length
69
+                [mheaders setValue:[NSString stringWithFormat:@"%lu",[postData length]] forKey:@"Content-Length"];
70
+                [mheaders setValue:@"100-continue" forKey:@"Expect"];
71
+                // appaned boundary to content-type
72
+                [mheaders setValue:[NSString stringWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@", boundary] forKey:@"content-type"];
73
+                [request setHTTPMethod: method];
74
+                [request setAllHTTPHeaderFields:mheaders];
75
+                onComplete(request, [formData length]);
60 76
             }
61
-            // set content-length
62
-            [mheaders setValue:[NSString stringWithFormat:@"%lu",[postData length]] forKey:@"Content-Length"];
63
-            [mheaders setValue:@"100-continue" forKey:@"Expect"];
64
-            // appaned boundary to content-type
65
-            [mheaders setValue:[NSString stringWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@", boundary] forKey:@"content-type"];
66
-            [request setHTTPMethod: method];
67
-            [request setAllHTTPHeaderFields:mheaders];
68
-            onComplete(request, [formData length]);
69 77
         }];
70 78
 
71 79
     });
@@ -91,8 +99,8 @@
91 99
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
92 100
         NSMutableData * blobData;
93 101
         long size = -1;
94
-        // if method is POST or PUT, convert data string format
95
-        if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
102
+        // if method is POST, PUT or PATCH, convert data string format
103
+        if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"] || [[method lowercaseString] isEqualToString:@"patch"]) {
96 104
             // generate octet-stream body
97 105
             if(body != nil) {
98 106
                 __block NSString * cType = [[self class] getHeaderIgnoreCases:@"content-type" fromHeaders:mheaders];
@@ -109,12 +117,21 @@
109 117
                     orgPath = [RNFetchBlobFS getPathOfAsset:orgPath];
110 118
                     if([orgPath hasPrefix:AL_PREFIX])
111 119
                     {
112
-                        [RNFetchBlobFS readFile:orgPath encoding:@"utf8" resolver:nil rejecter:nil onComplete:^(NSData *content) {
113
-                            [request setHTTPBody:content];
114
-                            [request setHTTPMethod: method];
115
-                            [request setAllHTTPHeaderFields:mheaders];
116
-                            onComplete(request, [content length]);
120
+                        
121
+                        [RNFetchBlobFS readFile:orgPath encoding:nil onComplete:^(NSData *content, NSString * err) {
122
+                            if(err != nil)
123
+                            {
124
+                                onComplete(nil, nil);
125
+                            }
126
+                            else
127
+                            {
128
+                                [request setHTTPBody:content];
129
+                                [request setHTTPMethod: method];
130
+                                [request setAllHTTPHeaderFields:mheaders];
131
+                                onComplete(request, [content length]);
132
+                            }
117 133
                         }];
134
+                        
118 135
                         return;
119 136
                     }
120 137
                     size = [[[NSFileManager defaultManager] attributesOfItemAtPath:orgPath error:nil] fileSize];
@@ -161,11 +178,11 @@
161 178
     });
162 179
 }
163 180
 
164
-+(void) buildFormBody:(NSArray *)form boundary:(NSString *)boundary onComplete:(void(^)(NSData * formData))onComplete
181
++(void) buildFormBody:(NSArray *)form boundary:(NSString *)boundary onComplete:(void(^)(NSData * formData, BOOL hasError))onComplete
165 182
 {
166 183
     __block NSMutableData * formData = [[NSMutableData alloc] init];
167 184
     if(form == nil)
168
-        onComplete(nil);
185
+        onComplete(nil, NO);
169 186
     else
170 187
     {
171 188
         __block int i = 0;
@@ -202,7 +219,13 @@
202 219
                     {
203 220
                         NSString * orgPath = [content substringFromIndex:[FILE_PREFIX length]];
204 221
                         orgPath = [RNFetchBlobFS getPathOfAsset:orgPath];
205
-                        [RNFetchBlobFS readFile:orgPath encoding:@"utf8" resolver:nil rejecter:nil onComplete:^(NSData *content) {
222
+
223
+                        [RNFetchBlobFS readFile:orgPath encoding:nil onComplete:^(NSData *content, NSString * err) {
224
+                            if(err != nil)
225
+                            {
226
+                                onComplete(formData, YES);
227
+                                return;
228
+                            }
206 229
                             NSString * filename = [field valueForKey:@"filename"];
207 230
                             [formData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
208 231
                             [formData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", name, filename] dataUsingEncoding:NSUTF8StringEncoding]];
@@ -217,7 +240,7 @@
217 240
                             }
218 241
                             else
219 242
                             {
220
-                                onComplete(formData);
243
+                                onComplete(formData, NO);
221 244
                                 getFieldData = nil;
222 245
                             }
223 246
                         }];
@@ -242,7 +265,7 @@
242 265
             }
243 266
             else
244 267
             {
245
-                onComplete(formData);
268
+                onComplete(formData, NO);
246 269
                 getFieldData = nil;
247 270
             }
248 271
 

+ 2
- 2
package.json 查看文件

@@ -1,6 +1,6 @@
1 1
 {
2 2
   "name": "react-native-fetch-blob",
3
-  "version": "0.10.3-beta.1",
3
+  "version": "0.10.4",
4 4
   "description": "A module provides upload, download, and files access API. Supports file stream read/write for process large files.",
5 5
   "main": "index.js",
6 6
   "scripts": {
@@ -59,4 +59,4 @@
59 59
     "smartt <github@eriksmartt.com>",
60 60
     ""
61 61
   ]
62
-}
62
+}

+ 1
- 1
polyfill/Blob.js 查看文件

@@ -113,7 +113,7 @@ export default class Blob extends EventTarget {
113 113
           formArray.push('\r\n--'+boundary+'\r\n')
114 114
           let part = parts[i]
115 115
           for(let j in part.headers) {
116
-            formArray.push(j + ': ' +part.headers[j] + ';\r\n')
116
+            formArray.push(j + ': ' +part.headers[j] + '\r\n')
117 117
           }
118 118
           formArray.push('\r\n')
119 119
           if(part.isRNFetchBlobPolyfill)

+ 0
- 2
polyfill/Fetch.js 查看文件

@@ -32,7 +32,6 @@ class RNFetchBlobFetchPolyfill {
32 32
       options.headers['Content-Type'] = ctype || ctypeH
33 33
       options.headers['content-type'] = ctype || ctypeH
34 34
       options.method = options.method || 'GET'
35
-
36 35
       if(body) {
37 36
         // When the request body is an instance of FormData, create a Blob cache
38 37
         // to upload the body.
@@ -55,7 +54,6 @@ class RNFetchBlobFetchPolyfill {
55 54
         else
56 55
           promise = Promise.resolve(body)
57 56
       }
58
-
59 57
       // task is a progress reportable and cancellable Promise, however,
60 58
       // task.then is not, so we have to extend task.then with progress and
61 59
       // cancel function