Skip to content

Commit 3aec419

Browse files
author
Guy Blank
committed
support upload task + recieve finish event from background
1 parent fd81e46 commit 3aec419

File tree

3 files changed

+74
-59
lines changed

3 files changed

+74
-59
lines changed

ios/RNFetchBlobNetwork.m

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ - (id)init {
6363
+ (RNFetchBlobNetwork* _Nullable)sharedInstance {
6464
static id _sharedInstance = nil;
6565
static dispatch_once_t onceToken;
66-
66+
6767
dispatch_once(&onceToken, ^{
6868
_sharedInstance = [[self alloc] init];
6969
});
@@ -135,14 +135,8 @@ - (void) enableUploadProgress:(NSString *) taskId config:(RNFetchBlobProgress *)
135135

136136
- (void) cancelRequest:(NSString *)taskId
137137
{
138-
NSURLSessionDataTask * task;
139-
140138
@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];
146140
}
147141
}
148142

ios/RNFetchBlobRequest.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
@property (nullable, nonatomic) NSError * error;
3333
@property (nullable, nonatomic) RNFetchBlobProgress *progressConfig;
3434
@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;
3637

3738
- (void) sendRequest:(NSDictionary * _Nullable )options
3839
contentLength:(long)contentLength
@@ -42,6 +43,8 @@
4243
taskOperationQueue:(NSOperationQueue * _Nonnull)operationQueue
4344
callback:(_Nullable RCTResponseSenderBlock) callback;
4445

46+
- (void) cancelRequest:(NSString *)taskId;
47+
4548
@end
4649

4750
#endif /* RNFetchBlobRequest_h */

ios/RNFetchBlobRequest.m

Lines changed: 68 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,24 @@
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

1933
typedef 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

Comments
 (0)