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,16 @@ - (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+
104+ if (uploadTask && ![[NSFileManager defaultManager ] fileExistsAtPath: [NSURL URLWithString: filepath].path]) {
105+ RCTLog (@" [RNFetchBlobRequest] sendRequest uploadTask file doesn't exist %@ " , filepath);
106+ callback (@[@" uploadTask file doesn't exist" , @" " , [NSNull null ]]);
107+ return ;
108+ }
109+
85110 // when followRedirect not set in options, defaults to TRUE
86111 followRedirect = [options valueForKey: @" followRedirect" ] == nil ? YES : [[options valueForKey: @" followRedirect" ] boolValue ];
87112 isIncrement = [[options valueForKey: @" increment" ] boolValue ];
@@ -104,7 +129,6 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
104129
105130 NSString * path = [self .options valueForKey: CONFIG_FILE_PATH];
106131 NSString * key = [self .options valueForKey: CONFIG_KEY];
107- NSURLSession * session;
108132
109133 bodyLength = contentLength;
110134
@@ -117,6 +141,7 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
117141 defaultConfigObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: taskId];
118142 }
119143
144+
120145 // request timeout, -1 if not set in options
121146 float timeout = [options valueForKey: @" timeout" ] == nil ? -1 : [[options valueForKey: @" timeout" ] floatValue ];
122147
@@ -125,7 +150,7 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
125150 }
126151
127152 defaultConfigObject.HTTPMaximumConnectionsPerHost = 10 ;
128- session = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: operationQueue];
153+ _session = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: operationQueue];
129154
130155 if (path || [self .options valueForKey: CONFIG_USE_TEMP]) {
131156 respFile = YES ;
@@ -157,8 +182,19 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
157182 respFile = NO ;
158183 }
159184
160- self.task = [session dataTaskWithRequest: req];
161- [self .task resume ];
185+ __block NSURLSessionTask * task;
186+
187+ if (uploadTask)
188+ {
189+ task = [_session uploadTaskWithRequest: req fromFile: [NSURL URLWithString: filepath]];
190+ }
191+ else
192+ {
193+ task = [_session dataTaskWithRequest: req];
194+ }
195+
196+ [taskTable setObject: task forKey: taskId];
197+ [task resume ];
162198
163199 // network status indicator
164200 if ([[options objectForKey: CONFIG_INDICATOR] boolValue ]) {
@@ -182,6 +218,7 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
182218// set expected content length on response received
183219- (void ) URLSession : (NSURLSession *)session dataTask : (NSURLSessionDataTask *)dataTask didReceiveResponse : (NSURLResponse *)response completionHandler : (void (^)(NSURLSessionResponseDisposition ))completionHandler
184220{
221+ NSLog (@" sess didReceiveResponse" );
185222 expectedBytes = [response expectedContentLength ];
186223
187224 NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
@@ -207,7 +244,7 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
207244
208245 partBuffer = [[NSMutableData alloc ] init ];
209246 completionHandler (NSURLSessionResponseAllow );
210-
247+
211248 return ;
212249 } else {
213250 self.isServerPush = [[respCType lowercaseString ] RNFBContainsString: @" multipart/x-mixed-replace;" ];
@@ -269,42 +306,6 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
269306 NSLog (@" oops" );
270307 }
271308
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-
308309 completionHandler (NSURLSessionResponseAllow );
309310}
310311
@@ -328,11 +329,7 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
328329 chunkString = [[NSString alloc ] initWithData: data encoding: NSUTF8StringEncoding];
329330 }
330331
331- if (respFile) {
332- [writeStream write: [data bytes ] maxLength: [data length ]];
333- } else {
334- [respData appendData: data];
335- }
332+ [respData appendData: data];
336333
337334 if (expectedBytes == 0 ) {
338335 return ;
@@ -353,8 +350,16 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
353350 }
354351}
355352
353+ - (void ) cancelRequest : (NSString *)taskId
354+ {
355+ NSURLSessionDataTask * task = [taskTable objectForKey: taskId];
356+ if (task != nil && task.state == NSURLSessionTaskStateRunning )
357+ [task cancel ];
358+ }
359+
356360- (void ) URLSession : (NSURLSession *)session didBecomeInvalidWithError : (nullable NSError *)error
357361{
362+ RCTLog (@" [RNFetchBlobRequest] session didBecomeInvalidWithError %@ " , [error description ]);
358363 if ([session isEqual: session]) {
359364 session = nil ;
360365 }
@@ -363,7 +368,7 @@ - (void) URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable
363368
364369- (void ) URLSession : (NSURLSession *)session task : (NSURLSessionTask *)task didCompleteWithError : (NSError *)error
365370{
366-
371+ RCTLog ( @" [RNFetchBlobRequest] session didCompleteWithError %@ " , [error description ]);
367372 self.error = error;
368373 NSString * errMsg;
369374 NSString * respStr;
@@ -416,10 +421,17 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCom
416421 respStr ?: [NSNull null ]
417422 ]);
418423
424+ @synchronized (taskTable)
425+ {
426+ if ([taskTable objectForKey: taskId] == nil )
427+ NSLog (@" object released by ARC." );
428+ else
429+ [taskTable removeObjectForKey: taskId];
430+ }
431+
419432 respData = nil ;
420433 receivedBytes = 0 ;
421434 [session finishTasksAndInvalidate ];
422-
423435}
424436
425437// upload progress handler
@@ -430,7 +442,7 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSen
430442 }
431443
432444 NSNumber * now = [NSNumber numberWithFloat: ((float )totalBytesWritten/(float )totalBytesExpectedToWrite)];
433-
445+
434446 if ([self .uploadProgressConfig shouldReport: now]) {
435447 [self .bridge.eventDispatcher
436448 sendDeviceEventWithName: EVENT_PROGRESS_UPLOAD
@@ -456,7 +468,19 @@ - (void) URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthentica
456468
457469- (void ) URLSessionDidFinishEventsForBackgroundURLSession : (NSURLSession *)session
458470{
459- NSLog (@" sess done in background" );
471+ RCTLog (@" [RNFetchBlobRequest] session done in background" );
472+ dispatch_async (dispatch_get_main_queue (), ^{
473+ id <UIApplicationDelegate> appDelegate = [UIApplication sharedApplication ].delegate ;
474+ SEL selector = NSSelectorFromString (@" backgroundTransferCompletionHandler" );
475+ if ([appDelegate respondsToSelector: selector]) {
476+ void (^completionHandler)() = [appDelegate performSelector: selector];
477+ if (completionHandler != nil ) {
478+ completionHandler ();
479+ completionHandler = nil ;
480+ }
481+ }
482+
483+ });
460484}
461485
462486- (void ) URLSession : (NSURLSession *)session task : (NSURLSessionTask *)task willPerformHTTPRedirection : (NSHTTPURLResponse *)response newRequest : (NSURLRequest *)request completionHandler : (void (^)(NSURLRequest * _Nullable))completionHandler
0 commit comments