1111#import " RNFetchBlobFS.h"
1212#import " RNFetchBlobConst.h"
1313#import " RNFetchBlobReqBuilder.h"
14+ #if __has_include(<React/RCTLog.h>)
15+ #import < React/RCTLog.h>
16+ #else
17+ #import " RCTLog.h"
18+ #endif
1419
1520#import " IOS7Polyfill.h"
1621#import < CommonCrypto/CommonDigest.h>
1722
23+ NSMapTable * taskTable;
24+
25+ __attribute__ ((constructor))
26+ static void initialize_tables() {
27+ if (taskTable == nil )
28+ {
29+ taskTable = [[NSMapTable alloc ] init ];
30+ }
31+ }
1832
1933typedef NS_ENUM (NSUInteger , ResponseFormat) {
2034 UTF8,
@@ -36,6 +50,7 @@ @interface RNFetchBlobRequest ()
3650 ResponseFormat responseFormat;
3751 BOOL followRedirect;
3852 BOOL backgroundTask;
53+ BOOL uploadTask;
3954}
4055
4156@end
@@ -82,6 +97,10 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
8297 self.options = options;
8398
8499 backgroundTask = [[options valueForKey: @" IOSBackgroundTask" ] boolValue ];
100+ uploadTask = [options valueForKey: @" IOSUploadTask" ] == nil ? NO : [[options valueForKey: @" IOSUploadTask" ] boolValue ];
101+
102+ NSString * filepath = [options valueForKey: @" uploadFilePath" ];
103+
85104 // when followRedirect not set in options, defaults to TRUE
86105 followRedirect = [options valueForKey: @" followRedirect" ] == nil ? YES : [[options valueForKey: @" followRedirect" ] boolValue ];
87106 isIncrement = [[options valueForKey: @" increment" ] boolValue ];
@@ -104,7 +123,6 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
104123
105124 NSString * path = [self .options valueForKey: CONFIG_FILE_PATH];
106125 NSString * key = [self .options valueForKey: CONFIG_KEY];
107- NSURLSession * session;
108126
109127 bodyLength = contentLength;
110128
@@ -117,6 +135,7 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
117135 defaultConfigObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: taskId];
118136 }
119137
138+
120139 // request timeout, -1 if not set in options
121140 float timeout = [options valueForKey: @" timeout" ] == nil ? -1 : [[options valueForKey: @" timeout" ] floatValue ];
122141
@@ -125,7 +144,7 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
125144 }
126145
127146 defaultConfigObject.HTTPMaximumConnectionsPerHost = 10 ;
128- session = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: operationQueue];
147+ _session = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: operationQueue];
129148
130149 if (path || [self .options valueForKey: CONFIG_USE_TEMP]) {
131150 respFile = YES ;
@@ -157,8 +176,19 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
157176 respFile = NO ;
158177 }
159178
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 ];
162192
163193 // network status indicator
164194 if ([[options objectForKey: CONFIG_INDICATOR] boolValue ]) {
@@ -182,6 +212,7 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
182212// set expected content length on response received
183213- (void ) URLSession : (NSURLSession *)session dataTask : (NSURLSessionDataTask *)dataTask didReceiveResponse : (NSURLResponse *)response completionHandler : (void (^)(NSURLSessionResponseDisposition ))completionHandler
184214{
215+ NSLog (@" sess didReceiveResponse" );
185216 expectedBytes = [response expectedContentLength ];
186217
187218 NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
@@ -207,7 +238,7 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
207238
208239 partBuffer = [[NSMutableData alloc ] init ];
209240 completionHandler (NSURLSessionResponseAllow );
210-
241+
211242 return ;
212243 } else {
213244 self.isServerPush = [[respCType lowercaseString ] RNFBContainsString: @" multipart/x-mixed-replace;" ];
@@ -269,42 +300,6 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
269300 NSLog (@" oops" );
270301 }
271302
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-
308303 completionHandler (NSURLSessionResponseAllow );
309304}
310305
@@ -328,11 +323,7 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
328323 chunkString = [[NSString alloc ] initWithData: data encoding: NSUTF8StringEncoding];
329324 }
330325
331- if (respFile) {
332- [writeStream write: [data bytes ] maxLength: [data length ]];
333- } else {
334- [respData appendData: data];
335- }
326+ [respData appendData: data];
336327
337328 if (expectedBytes == 0 ) {
338329 return ;
@@ -353,8 +344,16 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
353344 }
354345}
355346
347+ - (void ) cancelRequest : (NSString *)taskId
348+ {
349+ NSURLSessionDataTask * task = [taskTable objectForKey: taskId];
350+ if (task != nil && task.state == NSURLSessionTaskStateRunning )
351+ [task cancel ];
352+ }
353+
356354- (void ) URLSession : (NSURLSession *)session didBecomeInvalidWithError : (nullable NSError *)error
357355{
356+ RCTLog (@" [RNFetchBlobRequest] session didBecomeInvalidWithError %@ " , [error description ]);
358357 if ([session isEqual: session]) {
359358 session = nil ;
360359 }
@@ -363,7 +362,7 @@ - (void) URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable
363362
364363- (void ) URLSession : (NSURLSession *)session task : (NSURLSessionTask *)task didCompleteWithError : (NSError *)error
365364{
366-
365+ RCTLog ( @" [RNFetchBlobRequest] session didCompleteWithError %@ " , [error description ]);
367366 self.error = error;
368367 NSString * errMsg;
369368 NSString * respStr;
@@ -416,10 +415,17 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCom
416415 respStr ?: [NSNull null ]
417416 ]);
418417
418+ @synchronized (taskTable)
419+ {
420+ if ([taskTable objectForKey: taskId] == nil )
421+ NSLog (@" object released by ARC." );
422+ else
423+ [taskTable removeObjectForKey: taskId];
424+ }
425+
419426 respData = nil ;
420427 receivedBytes = 0 ;
421428 [session finishTasksAndInvalidate ];
422-
423429}
424430
425431// upload progress handler
@@ -430,7 +436,7 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSen
430436 }
431437
432438 NSNumber * now = [NSNumber numberWithFloat: ((float )totalBytesWritten/(float )totalBytesExpectedToWrite)];
433-
439+
434440 if ([self .uploadProgressConfig shouldReport: now]) {
435441 [self .bridge.eventDispatcher
436442 sendDeviceEventWithName: EVENT_PROGRESS_UPLOAD
@@ -456,7 +462,19 @@ - (void) URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthentica
456462
457463- (void ) URLSessionDidFinishEventsForBackgroundURLSession : (NSURLSession *)session
458464{
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+ });
460478}
461479
462480- (void ) URLSession : (NSURLSession *)session task : (NSURLSessionTask *)task willPerformHTTPRedirection : (NSHTTPURLResponse *)response newRequest : (NSURLRequest *)request completionHandler : (void (^)(NSURLRequest * _Nullable))completionHandler
0 commit comments