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 @@ @interface RNFetchBlobRequest ()
36
50
ResponseFormat responseFormat;
37
51
BOOL followRedirect;
38
52
BOOL backgroundTask;
53
+ BOOL uploadTask;
39
54
}
40
55
41
56
@end
@@ -83,8 +98,18 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
83
98
if (!self.keyChain ) {
84
99
self.keyChain = [[KeyChainDataSource alloc ] initWithMode: KSM_Identities];
85
100
}
86
-
101
+
87
102
backgroundTask = [[options valueForKey: @" IOSBackgroundTask" ] boolValue ];
103
+ uploadTask = [options valueForKey: @" IOSUploadTask" ] == nil ? NO : [[options valueForKey: @" IOSUploadTask" ] boolValue ];
104
+
105
+ NSString * filepath = [options valueForKey: @" uploadFilePath" ];
106
+
107
+ if (uploadTask && ![[NSFileManager defaultManager ] fileExistsAtPath: [NSURL URLWithString: filepath].path]) {
108
+ RCTLog (@" [RNFetchBlobRequest] sendRequest uploadTask file doesn't exist %@ " , filepath);
109
+ callback (@[@" uploadTask file doesn't exist" , @" " , [NSNull null ]]);
110
+ return ;
111
+ }
112
+
88
113
// when followRedirect not set in options, defaults to TRUE
89
114
followRedirect = [options valueForKey: @" followRedirect" ] == nil ? YES : [[options valueForKey: @" followRedirect" ] boolValue ];
90
115
isIncrement = [[options valueForKey: @" increment" ] boolValue ];
@@ -107,7 +132,6 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
107
132
108
133
NSString * path = [self .options valueForKey: CONFIG_FILE_PATH];
109
134
NSString * key = [self .options valueForKey: CONFIG_KEY];
110
- NSURLSession * session;
111
135
112
136
bodyLength = contentLength;
113
137
@@ -120,6 +144,7 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
120
144
defaultConfigObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: taskId];
121
145
}
122
146
147
+
123
148
// request timeout, -1 if not set in options
124
149
float timeout = [options valueForKey: @" timeout" ] == nil ? -1 : [[options valueForKey: @" timeout" ] floatValue ];
125
150
@@ -135,8 +160,8 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
135
160
defaultConfigObject.timeoutIntervalForResource = 60 ;
136
161
}
137
162
}
138
- session = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: operationQueue];
139
-
163
+ _session = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: operationQueue];
164
+
140
165
if (path || [self .options valueForKey: CONFIG_USE_TEMP]) {
141
166
respFile = YES ;
142
167
@@ -167,8 +192,19 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
167
192
respFile = NO ;
168
193
}
169
194
170
- self.task = [session dataTaskWithRequest: req];
171
- [self .task resume ];
195
+ __block NSURLSessionTask * task;
196
+
197
+ if (uploadTask)
198
+ {
199
+ task = [_session uploadTaskWithRequest: req fromFile: [NSURL URLWithString: filepath]];
200
+ }
201
+ else
202
+ {
203
+ task = [_session dataTaskWithRequest: req];
204
+ }
205
+
206
+ [taskTable setObject: task forKey: taskId];
207
+ [task resume ];
172
208
173
209
// network status indicator
174
210
if ([[options objectForKey: CONFIG_INDICATOR] boolValue ]) {
@@ -192,6 +228,7 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
192
228
// set expected content length on response received
193
229
- (void ) URLSession : (NSURLSession *)session dataTask : (NSURLSessionDataTask *)dataTask didReceiveResponse : (NSURLResponse *)response completionHandler : (void (^)(NSURLSessionResponseDisposition ))completionHandler
194
230
{
231
+ NSLog (@" sess didReceiveResponse" );
195
232
expectedBytes = [response expectedContentLength ];
196
233
197
234
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
@@ -278,43 +315,7 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
278
315
} else {
279
316
NSLog (@" oops" );
280
317
}
281
-
282
- if (respFile)
283
- {
284
- @try {
285
- NSFileManager * fm = [NSFileManager defaultManager ];
286
- NSString * folder = [destPath stringByDeletingLastPathComponent ];
287
-
288
- if (![fm fileExistsAtPath: folder]) {
289
- [fm createDirectoryAtPath: folder withIntermediateDirectories: YES attributes: NULL error: nil ];
290
- }
291
-
292
- // if not set overwrite in options, defaults to TRUE
293
- BOOL overwrite = [options valueForKey: @" overwrite" ] == nil ? YES : [[options valueForKey: @" overwrite" ] boolValue ];
294
- BOOL appendToExistingFile = [destPath RNFBContainsString: @" ?append=true" ];
295
-
296
- appendToExistingFile = !overwrite;
297
-
298
- // For solving #141 append response data if the file already exists
299
- // base on PR#139 @kejinliang
300
- if (appendToExistingFile) {
301
- destPath = [destPath stringByReplacingOccurrencesOfString: @" ?append=true" withString: @" " ];
302
- }
303
-
304
- if (![fm fileExistsAtPath: destPath]) {
305
- [fm createFileAtPath: destPath contents: [[NSData alloc ] init ] attributes: nil ];
306
- }
307
-
308
- writeStream = [[NSOutputStream alloc ] initToFileAtPath: destPath append: appendToExistingFile];
309
- [writeStream scheduleInRunLoop: [NSRunLoop currentRunLoop ] forMode: NSRunLoopCommonModes ];
310
- [writeStream open ];
311
- }
312
- @catch (NSException * ex)
313
- {
314
- NSLog (@" write file error" );
315
- }
316
- }
317
-
318
+
318
319
completionHandler (NSURLSessionResponseAllow );
319
320
}
320
321
@@ -338,11 +339,7 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
338
339
chunkString = [[NSString alloc ] initWithData: data encoding: NSUTF8StringEncoding];
339
340
}
340
341
341
- if (respFile) {
342
- [writeStream write: [data bytes ] maxLength: [data length ]];
343
- } else {
344
- [respData appendData: data];
345
- }
342
+ [respData appendData: data];
346
343
347
344
if (expectedBytes == 0 ) {
348
345
return ;
@@ -363,8 +360,16 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
363
360
}
364
361
}
365
362
363
+ - (void ) cancelRequest : (NSString *)taskId
364
+ {
365
+ NSURLSessionDataTask * task = [taskTable objectForKey: taskId];
366
+ if (task != nil && task.state == NSURLSessionTaskStateRunning )
367
+ [task cancel ];
368
+ }
369
+
366
370
- (void ) URLSession : (NSURLSession *)session didBecomeInvalidWithError : (nullable NSError *)error
367
371
{
372
+ RCTLog (@" [RNFetchBlobRequest] session didBecomeInvalidWithError %@ " , [error description ]);
368
373
if ([session isEqual: session]) {
369
374
session = nil ;
370
375
}
@@ -373,7 +378,7 @@ - (void) URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable
373
378
374
379
- (void ) URLSession : (NSURLSession *)session task : (NSURLSessionTask *)task didCompleteWithError : (NSError *)error
375
380
{
376
-
381
+ RCTLog ( @" [RNFetchBlobRequest] session didCompleteWithError %@ " , [error description ]);
377
382
self.error = error;
378
383
NSString * errMsg;
379
384
NSString * respStr;
@@ -426,10 +431,17 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCom
426
431
respStr ?: [NSNull null ]
427
432
]);
428
433
434
+ @synchronized (taskTable)
435
+ {
436
+ if ([taskTable objectForKey: taskId] == nil )
437
+ NSLog (@" object released by ARC." );
438
+ else
439
+ [taskTable removeObjectForKey: taskId];
440
+ }
441
+
429
442
respData = nil ;
430
443
receivedBytes = 0 ;
431
444
[session finishTasksAndInvalidate ];
432
-
433
445
}
434
446
435
447
// upload progress handler
@@ -490,7 +502,19 @@ - (void) URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthentica
490
502
491
503
- (void ) URLSessionDidFinishEventsForBackgroundURLSession : (NSURLSession *)session
492
504
{
493
- NSLog (@" sess done in background" );
505
+ RCTLog (@" [RNFetchBlobRequest] session done in background" );
506
+ dispatch_async (dispatch_get_main_queue (), ^{
507
+ id <UIApplicationDelegate> appDelegate = [UIApplication sharedApplication ].delegate ;
508
+ SEL selector = NSSelectorFromString (@" backgroundTransferCompletionHandler" );
509
+ if ([appDelegate respondsToSelector: selector]) {
510
+ void (^completionHandler)() = [appDelegate performSelector: selector];
511
+ if (completionHandler != nil ) {
512
+ completionHandler ();
513
+ completionHandler = nil ;
514
+ }
515
+ }
516
+
517
+ });
494
518
}
495
519
496
520
- (void ) URLSession : (NSURLSession *)session task : (NSURLSessionTask *)task willPerformHTTPRedirection : (NSHTTPURLResponse *)response newRequest : (NSURLRequest *)request completionHandler : (void (^)(NSURLRequest * _Nullable))completionHandler
0 commit comments