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
@@ -82,6 +97,16 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
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
+
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
+
85
110
// when followRedirect not set in options, defaults to TRUE
86
111
followRedirect = [options valueForKey: @" followRedirect" ] == nil ? YES : [[options valueForKey: @" followRedirect" ] boolValue ];
87
112
isIncrement = [[options valueForKey: @" increment" ] boolValue ];
@@ -104,7 +129,6 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
104
129
105
130
NSString * path = [self .options valueForKey: CONFIG_FILE_PATH];
106
131
NSString * key = [self .options valueForKey: CONFIG_KEY];
107
- NSURLSession * session;
108
132
109
133
bodyLength = contentLength;
110
134
@@ -117,6 +141,7 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
117
141
defaultConfigObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: taskId];
118
142
}
119
143
144
+
120
145
// request timeout, -1 if not set in options
121
146
float timeout = [options valueForKey: @" timeout" ] == nil ? -1 : [[options valueForKey: @" timeout" ] floatValue ];
122
147
@@ -125,7 +150,7 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
125
150
}
126
151
127
152
defaultConfigObject.HTTPMaximumConnectionsPerHost = 10 ;
128
- session = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: operationQueue];
153
+ _session = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: operationQueue];
129
154
130
155
if (path || [self .options valueForKey: CONFIG_USE_TEMP]) {
131
156
respFile = YES ;
@@ -157,8 +182,19 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
157
182
respFile = NO ;
158
183
}
159
184
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 ];
162
198
163
199
// network status indicator
164
200
if ([[options objectForKey: CONFIG_INDICATOR] boolValue ]) {
@@ -182,6 +218,7 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
182
218
// set expected content length on response received
183
219
- (void ) URLSession : (NSURLSession *)session dataTask : (NSURLSessionDataTask *)dataTask didReceiveResponse : (NSURLResponse *)response completionHandler : (void (^)(NSURLSessionResponseDisposition ))completionHandler
184
220
{
221
+ NSLog (@" sess didReceiveResponse" );
185
222
expectedBytes = [response expectedContentLength ];
186
223
187
224
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
@@ -207,7 +244,7 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
207
244
208
245
partBuffer = [[NSMutableData alloc ] init ];
209
246
completionHandler (NSURLSessionResponseAllow );
210
-
247
+
211
248
return ;
212
249
} else {
213
250
self.isServerPush = [[respCType lowercaseString ] RNFBContainsString: @" multipart/x-mixed-replace;" ];
@@ -269,42 +306,6 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
269
306
NSLog (@" oops" );
270
307
}
271
308
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
309
completionHandler (NSURLSessionResponseAllow );
309
310
}
310
311
@@ -328,11 +329,7 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
328
329
chunkString = [[NSString alloc ] initWithData: data encoding: NSUTF8StringEncoding];
329
330
}
330
331
331
- if (respFile) {
332
- [writeStream write: [data bytes ] maxLength: [data length ]];
333
- } else {
334
- [respData appendData: data];
335
- }
332
+ [respData appendData: data];
336
333
337
334
if (expectedBytes == 0 ) {
338
335
return ;
@@ -353,8 +350,16 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
353
350
}
354
351
}
355
352
353
+ - (void ) cancelRequest : (NSString *)taskId
354
+ {
355
+ NSURLSessionDataTask * task = [taskTable objectForKey: taskId];
356
+ if (task != nil && task.state == NSURLSessionTaskStateRunning )
357
+ [task cancel ];
358
+ }
359
+
356
360
- (void ) URLSession : (NSURLSession *)session didBecomeInvalidWithError : (nullable NSError *)error
357
361
{
362
+ RCTLog (@" [RNFetchBlobRequest] session didBecomeInvalidWithError %@ " , [error description ]);
358
363
if ([session isEqual: session]) {
359
364
session = nil ;
360
365
}
@@ -363,7 +368,7 @@ - (void) URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable
363
368
364
369
- (void ) URLSession : (NSURLSession *)session task : (NSURLSessionTask *)task didCompleteWithError : (NSError *)error
365
370
{
366
-
371
+ RCTLog ( @" [RNFetchBlobRequest] session didCompleteWithError %@ " , [error description ]);
367
372
self.error = error;
368
373
NSString * errMsg;
369
374
NSString * respStr;
@@ -416,10 +421,17 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCom
416
421
respStr ?: [NSNull null ]
417
422
]);
418
423
424
+ @synchronized (taskTable)
425
+ {
426
+ if ([taskTable objectForKey: taskId] == nil )
427
+ NSLog (@" object released by ARC." );
428
+ else
429
+ [taskTable removeObjectForKey: taskId];
430
+ }
431
+
419
432
respData = nil ;
420
433
receivedBytes = 0 ;
421
434
[session finishTasksAndInvalidate ];
422
-
423
435
}
424
436
425
437
// upload progress handler
@@ -430,7 +442,7 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSen
430
442
}
431
443
432
444
NSNumber * now = [NSNumber numberWithFloat: ((float )totalBytesWritten/(float )totalBytesExpectedToWrite)];
433
-
445
+
434
446
if ([self .uploadProgressConfig shouldReport: now]) {
435
447
[self .bridge.eventDispatcher
436
448
sendDeviceEventWithName: EVENT_PROGRESS_UPLOAD
@@ -456,7 +468,19 @@ - (void) URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthentica
456
468
457
469
- (void ) URLSessionDidFinishEventsForBackgroundURLSession : (NSURLSession *)session
458
470
{
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
+ });
460
484
}
461
485
462
486
- (void ) URLSession : (NSURLSession *)session task : (NSURLSessionTask *)task willPerformHTTPRedirection : (NSHTTPURLResponse *)response newRequest : (NSURLRequest *)request completionHandler : (void (^)(NSURLRequest * _Nullable))completionHandler
0 commit comments