Selaa lähdekoodia

support upload task + recieve finish event from background

Guy Blank 5 vuotta sitten
vanhempi
commit
3aec4191f9
3 muutettua tiedostoa jossa 74 lisäystä ja 59 poistoa
  1. 2
    8
      ios/RNFetchBlobNetwork.m
  2. 4
    1
      ios/RNFetchBlobRequest.h
  3. 68
    50
      ios/RNFetchBlobRequest.m

+ 2
- 8
ios/RNFetchBlobNetwork.m Näytä tiedosto

@@ -63,7 +63,7 @@ static void initialize_tables() {
63 63
 + (RNFetchBlobNetwork* _Nullable)sharedInstance {
64 64
     static id _sharedInstance = nil;
65 65
     static dispatch_once_t onceToken;
66
-
66
+    
67 67
     dispatch_once(&onceToken, ^{
68 68
         _sharedInstance = [[self alloc] init];
69 69
     });
@@ -135,14 +135,8 @@ static void initialize_tables() {
135 135
 
136 136
 - (void) cancelRequest:(NSString *)taskId
137 137
 {
138
-    NSURLSessionDataTask * task;
139
-    
140 138
     @synchronized ([RNFetchBlobNetwork class]) {
141
-        task = [self.requestsTable objectForKey:taskId].task;
142
-    }
143
-    
144
-    if (task && task.state == NSURLSessionTaskStateRunning) {
145
-        [task cancel];
139
+        [[self.requestsTable objectForKey:taskId] cancelRequest:taskId];
146 140
     }
147 141
 }
148 142
 

+ 4
- 1
ios/RNFetchBlobRequest.h Näytä tiedosto

@@ -32,7 +32,8 @@
32 32
 @property (nullable, nonatomic) NSError * error;
33 33
 @property (nullable, nonatomic) RNFetchBlobProgress *progressConfig;
34 34
 @property (nullable, nonatomic) RNFetchBlobProgress *uploadProgressConfig;
35
-@property (nullable, nonatomic, weak) NSURLSessionDataTask *task;
35
+//@property (nullable, nonatomic, weak) NSURLSessionDataTask *task;
36
+@property (nonatomic, strong) __block NSURLSession * session;
36 37
 
37 38
 - (void) sendRequest:(NSDictionary  * _Nullable )options
38 39
        contentLength:(long)contentLength
@@ -42,6 +43,8 @@
42 43
   taskOperationQueue:(NSOperationQueue * _Nonnull)operationQueue
43 44
             callback:(_Nullable RCTResponseSenderBlock) callback;
44 45
 
46
+- (void) cancelRequest:(NSString *)taskId;
47
+
45 48
 @end
46 49
 
47 50
 #endif /* RNFetchBlobRequest_h */

+ 68
- 50
ios/RNFetchBlobRequest.m Näytä tiedosto

@@ -11,10 +11,24 @@
11 11
 #import "RNFetchBlobFS.h"
12 12
 #import "RNFetchBlobConst.h"
13 13
 #import "RNFetchBlobReqBuilder.h"
14
+#if __has_include(<React/RCTLog.h>)
15
+#import <React/RCTLog.h>
16
+#else
17
+#import "RCTLog.h"
18
+#endif
14 19
 
15 20
 #import "IOS7Polyfill.h"
16 21
 #import <CommonCrypto/CommonDigest.h>
17 22
 
23
+NSMapTable * taskTable;
24
+
25
+__attribute__((constructor))
26
+static void initialize_tables() {
27
+    if(taskTable == nil)
28
+    {
29
+        taskTable = [[NSMapTable alloc] init];
30
+    }
31
+}
18 32
 
19 33
 typedef NS_ENUM(NSUInteger, ResponseFormat) {
20 34
     UTF8,
@@ -36,6 +50,7 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
36 50
     ResponseFormat responseFormat;
37 51
     BOOL followRedirect;
38 52
     BOOL backgroundTask;
53
+    BOOL uploadTask;
39 54
 }
40 55
 
41 56
 @end
@@ -82,6 +97,10 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
82 97
     self.options = options;
83 98
     
84 99
     backgroundTask = [[options valueForKey:@"IOSBackgroundTask"] boolValue];
100
+    uploadTask = [options valueForKey:@"IOSUploadTask"] == nil ? NO : [[options valueForKey:@"IOSUploadTask"] boolValue];
101
+    
102
+    NSString * filepath = [options valueForKey:@"uploadFilePath"];
103
+    
85 104
     // when followRedirect not set in options, defaults to TRUE
86 105
     followRedirect = [options valueForKey:@"followRedirect"] == nil ? YES : [[options valueForKey:@"followRedirect"] boolValue];
87 106
     isIncrement = [[options valueForKey:@"increment"] boolValue];
@@ -104,7 +123,6 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
104 123
     
105 124
     NSString * path = [self.options valueForKey:CONFIG_FILE_PATH];
106 125
     NSString * key = [self.options valueForKey:CONFIG_KEY];
107
-    NSURLSession * session;
108 126
     
109 127
     bodyLength = contentLength;
110 128
     
@@ -117,6 +135,7 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
117 135
         defaultConfigObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:taskId];
118 136
     }
119 137
     
138
+    
120 139
     // request timeout, -1 if not set in options
121 140
     float timeout = [options valueForKey:@"timeout"] == nil ? -1 : [[options valueForKey:@"timeout"] floatValue];
122 141
     
@@ -125,7 +144,7 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
125 144
     }
126 145
     
127 146
     defaultConfigObject.HTTPMaximumConnectionsPerHost = 10;
128
-    session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:operationQueue];
147
+    _session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:operationQueue];
129 148
     
130 149
     if (path || [self.options valueForKey:CONFIG_USE_TEMP]) {
131 150
         respFile = YES;
@@ -157,8 +176,19 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
157 176
         respFile = NO;
158 177
     }
159 178
     
160
-    self.task = [session dataTaskWithRequest:req];
161
-    [self.task resume];
179
+    __block NSURLSessionTask * task;
180
+    
181
+    if(uploadTask)
182
+    {
183
+        task = [_session uploadTaskWithRequest:req fromFile:[NSURL URLWithString:filepath]];
184
+    }
185
+    else
186
+    {
187
+        task = [_session dataTaskWithRequest:req];
188
+    }
189
+    
190
+    [taskTable setObject:task forKey:taskId];
191
+    [task resume];
162 192
     
163 193
     // network status indicator
164 194
     if ([[options objectForKey:CONFIG_INDICATOR] boolValue]) {
@@ -182,6 +212,7 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
182 212
 // set expected content length on response received
183 213
 - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
184 214
 {
215
+    NSLog(@"sess didReceiveResponse");
185 216
     expectedBytes = [response expectedContentLength];
186 217
     
187 218
     NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
@@ -207,7 +238,7 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
207 238
             
208 239
             partBuffer = [[NSMutableData alloc] init];
209 240
             completionHandler(NSURLSessionResponseAllow);
210
-
241
+            
211 242
             return;
212 243
         } else {
213 244
             self.isServerPush = [[respCType lowercaseString] RNFBContainsString:@"multipart/x-mixed-replace;"];
@@ -269,42 +300,6 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
269 300
         NSLog(@"oops");
270 301
     }
271 302
     
272
-    if (respFile)
273
-    {
274
-        @try{
275
-            NSFileManager * fm = [NSFileManager defaultManager];
276
-            NSString * folder = [destPath stringByDeletingLastPathComponent];
277
-            
278
-            if (![fm fileExistsAtPath:folder]) {
279
-                [fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:nil];
280
-            }
281
-            
282
-            // if not set overwrite in options, defaults to TRUE
283
-            BOOL overwrite = [options valueForKey:@"overwrite"] == nil ? YES : [[options valueForKey:@"overwrite"] boolValue];
284
-            BOOL appendToExistingFile = [destPath RNFBContainsString:@"?append=true"];
285
-            
286
-            appendToExistingFile = !overwrite;
287
-            
288
-            // For solving #141 append response data if the file already exists
289
-            // base on PR#139 @kejinliang
290
-            if (appendToExistingFile) {
291
-                destPath = [destPath stringByReplacingOccurrencesOfString:@"?append=true" withString:@""];
292
-            }
293
-            
294
-            if (![fm fileExistsAtPath:destPath]) {
295
-                [fm createFileAtPath:destPath contents:[[NSData alloc] init] attributes:nil];
296
-            }
297
-            
298
-            writeStream = [[NSOutputStream alloc] initToFileAtPath:destPath append:appendToExistingFile];
299
-            [writeStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
300
-            [writeStream open];
301
-        }
302
-        @catch(NSException * ex)
303
-        {
304
-            NSLog(@"write file error");
305
-        }
306
-    }
307
-    
308 303
     completionHandler(NSURLSessionResponseAllow);
309 304
 }
310 305
 
@@ -328,11 +323,7 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
328 323
         chunkString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
329 324
     }
330 325
     
331
-    if (respFile) {
332
-        [writeStream write:[data bytes] maxLength:[data length]];
333
-    } else {
334
-        [respData appendData:data];
335
-    }
326
+    [respData appendData:data];
336 327
     
337 328
     if (expectedBytes == 0) {
338 329
         return;
@@ -353,8 +344,16 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
353 344
     }
354 345
 }
355 346
 
347
+- (void) cancelRequest:(NSString *)taskId
348
+{
349
+    NSURLSessionDataTask * task = [taskTable objectForKey:taskId];
350
+    if(task != nil && task.state == NSURLSessionTaskStateRunning)
351
+        [task cancel];
352
+}
353
+
356 354
 - (void) URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error
357 355
 {
356
+    RCTLog(@"[RNFetchBlobRequest] session didBecomeInvalidWithError %@", [error description]);
358 357
     if ([session isEqual:session]) {
359 358
         session = nil;
360 359
     }
@@ -363,7 +362,7 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
363 362
 
364 363
 - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
365 364
 {
366
-    
365
+    RCTLog(@"[RNFetchBlobRequest] session didCompleteWithError %@", [error description]);
367 366
     self.error = error;
368 367
     NSString * errMsg;
369 368
     NSString * respStr;
@@ -416,10 +415,17 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
416 415
                respStr ?: [NSNull null]
417 416
                ]);
418 417
     
418
+    @synchronized(taskTable)
419
+    {
420
+        if([taskTable objectForKey:taskId] == nil)
421
+            NSLog(@"object released by ARC.");
422
+        else
423
+            [taskTable removeObjectForKey:taskId];
424
+    }
425
+    
419 426
     respData = nil;
420 427
     receivedBytes = 0;
421 428
     [session finishTasksAndInvalidate];
422
-    
423 429
 }
424 430
 
425 431
 // upload progress handler
@@ -430,7 +436,7 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
430 436
     }
431 437
     
432 438
     NSNumber * now = [NSNumber numberWithFloat:((float)totalBytesWritten/(float)totalBytesExpectedToWrite)];
433
-
439
+    
434 440
     if ([self.uploadProgressConfig shouldReport:now]) {
435 441
         [self.bridge.eventDispatcher
436 442
          sendDeviceEventWithName:EVENT_PROGRESS_UPLOAD
@@ -456,7 +462,19 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
456 462
 
457 463
 - (void) URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
458 464
 {
459
-    NSLog(@"sess done in background");
465
+    RCTLog(@"[RNFetchBlobRequest] session done in background");
466
+    dispatch_async(dispatch_get_main_queue(), ^{
467
+        id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
468
+        SEL selector = NSSelectorFromString(@"backgroundTransferCompletionHandler");
469
+        if ([appDelegate respondsToSelector:selector]) {
470
+            void(^completionHandler)() = [appDelegate performSelector:selector];
471
+            if (completionHandler != nil) {
472
+                completionHandler();
473
+                completionHandler = nil;
474
+            }
475
+        }
476
+        
477
+    });
460 478
 }
461 479
 
462 480
 - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler