Ben Hsieh преди 7 години
родител
ревизия
92455e1ec8

+ 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
 }

+ 6
- 3
android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java Целия файл

@@ -234,7 +234,8 @@ public class RNFetchBlobFS {
234 234
 
235 235
             InputStream fs;
236 236
             if(path.startsWith(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET)) {
237
-                fs = RNFetchBlob.RCTContext.getAssets().open(path.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, ""));
237
+                fs = RNFetchBlob.RCTContext.getAssets()
238
+                        .open(path.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, ""));
238 239
             }
239 240
             else {
240 241
                 fs = new FileInputStream(new File(path));
@@ -249,8 +250,9 @@ public class RNFetchBlobFS {
249 250
                 while ((cursor = fs.read(buffer)) != -1) {
250 251
                     encoder.encode(ByteBuffer.wrap(buffer).asCharBuffer());
251 252
                     String chunk = new String(buffer);
252
-                    if(cursor != bufferSize)
253
+                    if(cursor != bufferSize) {
253 254
                         chunk = chunk.substring(0, cursor);
255
+                    }
254 256
                     emitStreamEvent(streamId, "data", chunk);
255 257
                     if(tick > 0)
256 258
                         SystemClock.sleep(tick);
@@ -292,7 +294,8 @@ public class RNFetchBlobFS {
292 294
             buffer = null;
293 295
 
294 296
         } catch (Exception err) {
295
-            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.");
297
+            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.");
298
+            err.printStackTrace();
296 299
         }
297 300
     }
298 301
 

+ 18
- 8
android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java Целия файл

@@ -629,17 +629,26 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
629 629
                 DownloadManager dm = (DownloadManager) appCtx.getSystemService(Context.DOWNLOAD_SERVICE);
630 630
                 dm.query(query);
631 631
                 Cursor c = dm.query(query);
632
-                String error = null;
632
+
633
+
633 634
                 String filePath = null;
634 635
                 // the file exists in media content database
635 636
                 if (c.moveToFirst()) {
637
+                    // #297 handle failed request
638
+                    int statusCode = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
639
+                    if(statusCode == DownloadManager.STATUS_FAILED) {
640
+                        this.callback.invoke("Download manager failed to download from  " + this.url + ". Statu Code = " + statusCode, null, null);
641
+                        return;
642
+                    }
636 643
                     String contentUri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
637
-                    Uri uri = Uri.parse(contentUri);
638
-                    Cursor cursor = appCtx.getContentResolver().query(uri, new String[]{android.provider.MediaStore.Images.ImageColumns.DATA}, null, null, null);
639
-                    // use default destination of DownloadManager
640
-                    if (cursor != null) {
641
-                        cursor.moveToFirst();
642
-                        filePath = cursor.getString(0);
644
+                    if (contentUri != null) {
645
+                        Uri uri = Uri.parse(contentUri);
646
+                        Cursor cursor = appCtx.getContentResolver().query(uri, new String[]{android.provider.MediaStore.Images.ImageColumns.DATA}, null, null, null);
647
+                        // use default destination of DownloadManager
648
+                        if (cursor != null) {
649
+                            cursor.moveToFirst();
650
+                            filePath = cursor.getString(0);
651
+                        }
643 652
                     }
644 653
                 }
645 654
                 // When the file is not found in media content database, check if custom path exists
@@ -653,7 +662,8 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
653 662
                             this.callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, customDest);
654 663
 
655 664
                     } catch(Exception ex) {
656
-                        error = ex.getLocalizedMessage();
665
+                        ex.printStackTrace();
666
+                        this.callback.invoke(ex.getLocalizedMessage(), null);
657 667
                     }
658 668
                 }
659 669
                 else {

+ 29
- 13
ios/RNFetchBlob/RNFetchBlob.m Целия файл

@@ -314,7 +314,7 @@ RCT_EXPORT_METHOD(ls:(NSString *)path callback:(RCTResponseSenderBlock) callback
314 314
 #pragma mark - fs.stat
315 315
 RCT_EXPORT_METHOD(stat:(NSString *)target callback:(RCTResponseSenderBlock) callback)
316 316
 {
317
-    
317
+
318 318
     [RNFetchBlobFS getPathFromUri:target completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
319 319
         __block NSMutableArray * result;
320 320
         if(path != nil)
@@ -323,14 +323,14 @@ RCT_EXPORT_METHOD(stat:(NSString *)target callback:(RCTResponseSenderBlock) call
323 323
             BOOL exist = nil;
324 324
             BOOL isDir = nil;
325 325
             NSError * error = nil;
326
-            
326
+
327 327
             exist = [fm fileExistsAtPath:path isDirectory:&isDir];
328 328
             if(exist == NO) {
329 329
                 callback(@[[NSString stringWithFormat:@"failed to stat path `%@` for it is not exist or it is not exist", path]]);
330 330
                 return ;
331 331
             }
332 332
             result = [RNFetchBlobFS stat:path error:&error];
333
-            
333
+
334 334
             if(error == nil)
335 335
                 callback(@[[NSNull null], result]);
336 336
             else
@@ -389,7 +389,7 @@ RCT_EXPORT_METHOD(lstat:(NSString *)path callback:(RCTResponseSenderBlock) callb
389 389
 #pragma mark - fs.cp
390 390
 RCT_EXPORT_METHOD(cp:(NSString*)src toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback)
391 391
 {
392
-    
392
+
393 393
 //    path = [RNFetchBlobFS getPathOfAsset:path];
394 394
     [RNFetchBlobFS getPathFromUri:src completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
395 395
         NSError * error = nil;
@@ -401,14 +401,14 @@ RCT_EXPORT_METHOD(cp:(NSString*)src toPath:(NSString *)dest callback:(RCTRespons
401 401
         else
402 402
         {
403 403
             BOOL result = [[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
404
-            
404
+
405 405
             if(error == nil)
406 406
                 callback(@[[NSNull null], @YES]);
407 407
             else
408 408
                 callback(@[[error localizedDescription], @NO]);
409 409
         }
410 410
     }];
411
-    
411
+
412 412
 }
413 413
 
414 414
 
@@ -470,7 +470,7 @@ RCT_EXPORT_METHOD(readStream:(NSString *)path withEncoding:(NSString *)encoding
470 470
         else
471 471
             bufferSize = 4096;
472 472
     }
473
-    
473
+
474 474
     dispatch_async(fsQueue, ^{
475 475
         [RNFetchBlobFS readStream:path encoding:encoding bufferSize:bufferSize tick:tick streamId:streamId bridgeRef:_bridge];
476 476
     });
@@ -496,7 +496,7 @@ RCT_EXPORT_METHOD(cancelRequest:(NSString *)taskId callback:(RCTResponseSenderBl
496 496
 #pragma mark - net.enableProgressReport
497 497
 RCT_EXPORT_METHOD(enableProgressReport:(NSString *)taskId interval:(nonnull NSNumber*)interval count:(nonnull NSNumber*)count)
498 498
 {
499
-    
499
+
500 500
     RNFetchBlobProgress * cfg = [[RNFetchBlobProgress alloc] initWithType:Download interval:interval count:count];
501 501
     [RNFetchBlobNetwork enableProgressReport:taskId config:cfg];
502 502
 }
@@ -523,9 +523,10 @@ RCT_EXPORT_METHOD(previewDocument:(NSString*)uri scheme:(NSString *)scheme resol
523 523
     UIViewController *rootCtrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
524 524
     documentController.delegate = self;
525 525
     if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
526
-        dispatch_sync(dispatch_get_main_queue(), ^{
527
-            [documentController  presentOptionsMenuFromRect:rootCtrl.view.bounds inView:rootCtrl.view animated:YES];
528
-        });
526
+      CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0);
527
+      dispatch_sync(dispatch_get_main_queue(), ^{
528
+          [documentController  presentOptionsMenuFromRect:rect inView:rootCtrl.view animated:YES];
529
+      });
529 530
         resolve(@[[NSNull null]]);
530 531
     } else {
531 532
         reject(@"RNFetchBlob could not open document", @"scheme is not supported", nil);
@@ -541,7 +542,7 @@ RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString *)scheme resolver
541 542
     // NSURL * url = [[NSURL alloc] initWithString:uri];
542 543
     documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
543 544
     documentController.delegate = self;
544
-    
545
+
545 546
     if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
546 547
         dispatch_sync(dispatch_get_main_queue(), ^{
547 548
             [documentController presentPreviewAnimated:YES];
@@ -564,7 +565,7 @@ RCT_EXPORT_METHOD(excludeFromBackupKey:(NSString *)url resolver:(RCTPromiseResol
564 565
     } else {
565 566
         reject(@"RNFetchBlob could not open document", [error description], nil);
566 567
     }
567
-    
568
+
568 569
 }
569 570
 
570 571
 
@@ -580,11 +581,24 @@ RCT_EXPORT_METHOD(df:(RCTResponseSenderBlock)callback)
580 581
 }
581 582
 
582 583
 # pragma mark - getCookies
584
+
583 585
 RCT_EXPORT_METHOD(getCookies:(NSString *)url resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
584 586
 {
585 587
     resolve([RNFetchBlobNetwork getCookies:url]);
586 588
 }
587 589
 
590
+# pragma mark - removeCookie
591
+
592
+RCT_EXPORT_METHOD(removeCookies:(NSString *)domain resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
593
+{
594
+    NSError * err = nil;
595
+    [RNFetchBlobNetwork removeCookies:domain error:&err];
596
+    if(err)
597
+        reject(@"RNFetchBlob failed to remove cookie", @"RNFetchBlob failed to remove cookie", nil);
598
+    else
599
+        resolve(@[[NSNull null]]);
600
+}
601
+
588 602
 # pragma mark - check expired network events
589 603
 
590 604
 RCT_EXPORT_METHOD(emitExpiredEvent:(RCTResponseSenderBlock)callback)
@@ -593,4 +607,6 @@ RCT_EXPORT_METHOD(emitExpiredEvent:(RCTResponseSenderBlock)callback)
593 607
 }
594 608
 
595 609
 
610
+
611
+
596 612
 @end

+ 3
- 6
ios/RNFetchBlobFS.m Целия файл

@@ -758,8 +758,6 @@ NSMutableDictionary *fileStreams = nil;
758 758
 
759 759
 +(void) df:(RCTResponseSenderBlock)callback
760 760
 {
761
-    uint64_t totalSpace = 0;
762
-    uint64_t totalFreeSpace = 0;
763 761
     NSError *error = nil;
764 762
     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
765 763
     NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
@@ -767,11 +765,10 @@ NSMutableDictionary *fileStreams = nil;
767 765
     if (dictionary) {
768 766
         NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];
769 767
         NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
770
-        totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
771
-        totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
768
+        
772 769
         callback(@[[NSNull null], @{
773
-                  @"free" : [NSString stringWithFormat:@"%ld", totalFreeSpace],
774
-                  @"total" : [NSString stringWithFormat:@"%ld", totalSpace]
770
+                  @"free" : freeFileSystemSizeInBytes,
771
+                  @"total" : fileSystemSizeInBytes,
775 772
                 }]);
776 773
     } else {
777 774
         callback(@[@"failed to get storage usage."]);

+ 2
- 1
ios/RNFetchBlobNetwork.h Целия файл

@@ -49,9 +49,10 @@ typedef void(^DataTaskCompletionHander) (NSData * _Nullable resp, NSURLResponse
49 49
 - (nullable id) init;
50 50
 - (void) sendRequest;
51 51
 - (void) sendRequest:(NSDictionary  * _Nullable )options contentLength:(long)contentLength bridge:(RCTBridge * _Nullable)bridgeRef taskId:(NSString * _Nullable)taskId withRequest:(NSURLRequest * _Nullable)req callback:(_Nullable RCTResponseSenderBlock) callback;
52
++ (void) removeCookies:(NSString *) domain error:(NSError **)error;
52 53
 + (void) enableProgressReport:(NSString *) taskId config:(RNFetchBlobProgress *)config;
53 54
 + (void) enableUploadProgress:(NSString *) taskId config:(RNFetchBlobProgress *)config;
54
-+ (NSArray *) getCookies:(NSString *) url;
55
++ (NSDictionary *) getCookies:(NSString *) url;
55 56
 
56 57
 
57 58
 

+ 85
- 48
ios/RNFetchBlobNetwork.m Целия файл

@@ -37,7 +37,6 @@
37 37
 
38 38
 NSMapTable * taskTable;
39 39
 NSMapTable * expirationTable;
40
-NSMapTable * cookiesTable;
41 40
 NSMutableDictionary * progressTable;
42 41
 NSMutableDictionary * uploadProgressTable;
43 42
 
@@ -59,10 +58,6 @@ static void initialize_tables() {
59 58
     {
60 59
         uploadProgressTable = [[NSMutableDictionary alloc] init];
61 60
     }
62
-    if(cookiesTable == nil)
63
-    {
64
-        cookiesTable = [[NSMapTable alloc] init];
65
-    }
66 61
 }
67 62
 
68 63
 
@@ -116,48 +111,6 @@ NSOperationQueue *taskQueue;
116 111
     return self;
117 112
 }
118 113
 
119
-+ (NSArray *) getCookies:(NSString *) url
120
-{
121
-    NSString * hostname = [[NSURL URLWithString:url] host];
122
-    NSMutableArray * cookies = [NSMutableArray new];
123
-    NSArray * list = [cookiesTable objectForKey:hostname];
124
-    for(NSHTTPCookie * cookie in list)
125
-    {
126
-        NSMutableString * cookieStr = [[NSMutableString alloc] init];
127
-        [cookieStr appendString:cookie.name];
128
-        [cookieStr appendString:@"="];
129
-        [cookieStr appendString:cookie.value];
130
-
131
-        if(cookie.expiresDate == nil) {
132
-            [cookieStr appendString:@"; max-age=0"];
133
-        }
134
-        else {
135
-            [cookieStr appendString:@"; expires="];
136
-            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
137
-            [dateFormatter setDateFormat:@"EEE, dd MM yyyy HH:mm:ss ZZZ"];
138
-            NSString *strDate = [dateFormatter stringFromDate:cookie.expiresDate];
139
-            [cookieStr appendString:strDate];
140
-        }
141
-
142
-
143
-        [cookieStr appendString:@"; domain="];
144
-        [cookieStr appendString:hostname];
145
-        [cookieStr appendString:@"; path="];
146
-        [cookieStr appendString:cookie.path];
147
-
148
-
149
-        if (cookie.isSecure) {
150
-            [cookieStr appendString:@"; secure"];
151
-        }
152
-
153
-        if (cookie.isHTTPOnly) {
154
-            [cookieStr appendString:@"; httponly"];
155
-        }
156
-        [cookies addObject:cookieStr];
157
-    }
158
-    return cookies;
159
-}
160
-
161 114
 + (void) enableProgressReport:(NSString *) taskId config:(RNFetchBlobProgress *)config
162 115
 {
163 116
     if(progressTable == nil)
@@ -418,9 +371,10 @@ NSOperationQueue *taskQueue;
418 371
         // # 153 get cookies
419 372
         if(response.URL != nil)
420 373
         {
374
+            NSHTTPCookieStorage * cookieStore = [NSHTTPCookieStorage sharedHTTPCookieStorage];
421 375
             NSArray<NSHTTPCookie *> * cookies = [NSHTTPCookie cookiesWithResponseHeaderFields: headers forURL:response.URL];
422 376
             if(cookies != nil && [cookies count] > 0) {
423
-                [cookiesTable setObject:cookies forKey:response.URL.host];
377
+                [cookieStore setCookies:cookies forURL:response.URL mainDocumentURL:nil];
424 378
             }
425 379
         }
426 380
 
@@ -624,6 +578,89 @@ NSOperationQueue *taskQueue;
624 578
     }
625 579
 }
626 580
 
581
+# pragma mark - cookies handling API
582
+
583
++ (NSDictionary *) getCookies:(NSString *) domain
584
+{
585
+    NSMutableDictionary * result = [NSMutableDictionary new];
586
+    NSHTTPCookieStorage * cookieStore = [NSHTTPCookieStorage sharedHTTPCookieStorage];
587
+    for(NSHTTPCookie * cookie in [cookieStore cookies])
588
+    {
589
+        NSString * cDomain = [cookie domain];
590
+        if([result objectForKey:cDomain] == nil)
591
+        {
592
+            [result setObject:[NSMutableArray new] forKey:cDomain];
593
+        }
594
+        if([cDomain isEqualToString:domain] || [domain length] == 0)
595
+        {
596
+            NSMutableString * cookieStr = [[NSMutableString alloc] init];
597
+            cookieStr = [[self class] getCookieString:cookie];
598
+            NSMutableArray * ary = [result objectForKey:cDomain];
599
+            [ary addObject:cookieStr];
600
+            [result setObject:ary forKey:cDomain];
601
+        }
602
+    }
603
+    return result;
604
+}
605
+
606
+// remove cookies for given domain, if domain is empty remove all cookies in shared cookie storage.
607
++ (void) removeCookies:(NSString *) domain error:(NSError **)error
608
+{
609
+    @try
610
+    {
611
+        NSHTTPCookieStorage * cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage];
612
+        for(NSHTTPCookie * cookie in [cookies cookies])
613
+        {
614
+            BOOL shouldRemove = domain == nil || [domain length] < 1 || [[cookie domain] isEqualToString:domain];
615
+            if(shouldRemove)
616
+            {
617
+                [cookies deleteCookie:cookie];
618
+            }
619
+        }
620
+    }
621
+    @catch(NSError * err)
622
+    {
623
+        *error = err;
624
+    }
625
+}
626
+
627
+// convert NSHTTPCookie to string
628
++ (NSString *) getCookieString:(NSHTTPCookie *) cookie
629
+{
630
+    NSMutableString * cookieStr = [[NSMutableString alloc] init];
631
+    [cookieStr appendString:cookie.name];
632
+    [cookieStr appendString:@"="];
633
+    [cookieStr appendString:cookie.value];
634
+    
635
+    if(cookie.expiresDate == nil) {
636
+        [cookieStr appendString:@"; max-age=0"];
637
+    }
638
+    else {
639
+        [cookieStr appendString:@"; expires="];
640
+        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
641
+        [dateFormatter setDateFormat:@"EEE, dd MM yyyy HH:mm:ss ZZZ"];
642
+        NSString *strDate = [dateFormatter stringFromDate:cookie.expiresDate];
643
+        [cookieStr appendString:strDate];
644
+    }
645
+    
646
+    
647
+    [cookieStr appendString:@"; domain="];
648
+    [cookieStr appendString: [cookie domain]];
649
+    [cookieStr appendString:@"; path="];
650
+    [cookieStr appendString:cookie.path];
651
+    
652
+    
653
+    if (cookie.isSecure) {
654
+        [cookieStr appendString:@"; secure"];
655
+    }
656
+    
657
+    if (cookie.isHTTPOnly) {
658
+        [cookieStr appendString:@"; httponly"];
659
+    }
660
+    return cookieStr;
661
+
662
+}
663
+
627 664
 + (void) cancelRequest:(NSString *)taskId
628 665
 {
629 666
     NSURLSessionDataTask * task = [taskTable objectForKey:taskId];

+ 6
- 4
ios/RNFetchBlobReqBuilder.m Целия файл

@@ -99,8 +99,8 @@
99 99
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
100 100
         NSMutableData * blobData;
101 101
         long size = -1;
102
-        // if method is POST or PUT, convert data string format
103
-        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"]) {
104 104
             // generate octet-stream body
105 105
             if(body != nil) {
106 106
                 __block NSString * cType = [[self class] getHeaderIgnoreCases:@"content-type" fromHeaders:mheaders];
@@ -201,16 +201,18 @@
201 201
                 RCTLogWarn(@"RNFetchBlob multipart request builder has found a field without `data` or `name` property, the field will be removed implicitly.");
202 202
                 return;
203 203
             }
204
-            contentType = contentType == nil ? @"application/octet-stream" : contentType;
204
+
205 205
             // field is a text field
206 206
             if([field valueForKey:@"filename"] == nil || content == nil) {
207
+                contentType = contentType == nil ? @"text/plain" : contentType;
207 208
                 [formData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
208 209
                 [formData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", name] dataUsingEncoding:NSUTF8StringEncoding]];
209
-                [formData appendData:[[NSString stringWithFormat:@"Content-Type: text/plain\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
210
+                [formData appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", contentType] dataUsingEncoding:NSUTF8StringEncoding]];
210 211
                 [formData appendData:[[NSString stringWithFormat:@"%@\r\n", content] dataUsingEncoding:NSUTF8StringEncoding]];
211 212
             }
212 213
             // field contains a file
213 214
             else {
215
+                contentType = contentType == nil ? @"application/octet-stream" : contentType;
214 216
                 NSMutableData * blobData;
215 217
                 if(content != nil)
216 218
                 {