Skip to content
This repository has been archived by the owner on Mar 16, 2019. It is now read-only.

Commit

Permalink
Fix NSURLSession progress report issue #37
Browse files Browse the repository at this point in the history
  • Loading branch information
wkh237 committed Jul 4, 2016
1 parent ea478fa commit 1b2d9a7
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 90 deletions.
6 changes: 3 additions & 3 deletions src/ios/RNFetchBlobNetwork.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
typedef void(^CompletionHander)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error);
typedef void(^DataTaskCompletionHander) (NSData * _Nullable resp, NSURLResponse * _Nullable response, NSError * _Nullable error);

@interface RNFetchBlobNetwork : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, UIApplicationDelegate>
@interface RNFetchBlobNetwork : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate>

@property (nullable, nonatomic) NSString * taskId;
@property (nonatomic) int expectedBytes;
Expand All @@ -25,8 +25,8 @@ typedef void(^DataTaskCompletionHander) (NSData * _Nullable resp, NSURLResponse
@property (nullable, nonatomic) RCTBridge * bridge;
@property (nullable, nonatomic) NSDictionary * options;
@property (nullable, nonatomic) RNFetchBlobFS * fileStream;
//@property (strong, nonatomic) CompletionHander fileTaskCompletionHandler;
//@property (strong, nonatomic) DataTaskCompletionHander dataTaskCompletionHandler;
@property (strong, nonatomic) CompletionHander fileTaskCompletionHandler;
@property (strong, nonatomic) DataTaskCompletionHander dataTaskCompletionHandler;
@property (nullable, nonatomic) NSError * error;


Expand Down
177 changes: 90 additions & 87 deletions src/ios/RNFetchBlobNetwork.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@
//
////////////////////////////////////////

@interface RNFetchBlobNetwork ()
{
BOOL * respFile;
NSString * destPath;
NSOutputStream * writeStream;
long bodyLength;
}

@end

@implementation RNFetchBlobNetwork

NSOperationQueue *taskQueue;
Expand All @@ -32,8 +42,8 @@ @implementation RNFetchBlobNetwork
@synthesize callback;
@synthesize bridge;
@synthesize options;
//@synthesize fileTaskCompletionHandler;
//@synthesize dataTaskCompletionHandler;
@synthesize fileTaskCompletionHandler;
@synthesize dataTaskCompletionHandler;
@synthesize error;


Expand Down Expand Up @@ -73,83 +83,28 @@ - (void) sendRequest:(NSDictionary * _Nullable )options bridge:(RCTBridge * _Nu
NSString * ext = [self.options valueForKey:CONFIG_FILE_EXT];
NSURLSession * session;

bodyLength = [[req HTTPBody] length];

// the session trust any SSL certification
if([options valueForKey:CONFIG_TRUSTY] != nil)

NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:taskId];
session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];

if(path != nil || [self.options valueForKey:CONFIG_USE_TEMP]!= nil)
{
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];
respFile = YES;
if(path != nil)
destPath = path;
else
destPath = [RNFetchBlobFS getTempPath:taskId withExtension:[self.options valueForKey:CONFIG_FILE_EXT]];
}
// the session validates SSL certification, self-signed certification will be aborted
else
{
session = [NSURLSession sharedSession];
}

// file will be stored at a specific path
if( path != nil) {

// self.fileTaskCompletionHandler = ;
NSURLSessionDownloadTask * task = [session downloadTaskWithRequest:req completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if(error != nil) {
callback(@[[error localizedDescription]]);
return;
}
NSError * taskErr;
NSFileManager * fm = [NSFileManager defaultManager];
// move temp file to desination
[fm moveItemAtURL:location toURL:[NSURL fileURLWithPath:path] error:&taskErr];
if(taskErr != nil) {
callback(@[[taskErr localizedDescription]]);
return;
}
callback(@[[NSNull null], path]);
// prevent memory leaks
self.respData = nil;
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}];
[task resume];
}
// file will be stored at tmp path
else if ( [self.options valueForKey:CONFIG_USE_TEMP]!= nil ) {

// self.fileTaskCompletionHandler;
NSURLSessionDownloadTask * task = [session downloadTaskWithRequest:req completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if(error != nil) {
callback(@[[error localizedDescription]]);
return;
}
NSError * taskErr;
NSFileManager * fm = [NSFileManager defaultManager];
NSString * tmpPath = [RNFetchBlobFS getTempPath:self.taskId withExtension:[self.options valueForKey:CONFIG_FILE_EXT]];
// move temp file to desination
[fm moveItemAtURL:location toURL:[NSURL fileURLWithPath:tmpPath] error:&taskErr];
if(taskErr != nil) {
callback(@[[taskErr localizedDescription]]);
return;
}
callback(@[[NSNull null], tmpPath]);
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
// prevent memory leaks
self.respData = nil;
}];
[task resume];
}
// base64 response
else {
// self.dataTaskCompletionHandler = ;
NSURLSessionDataTask * task = [session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable resp, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if(error != nil) {
callback(@[[error localizedDescription]]);
return;
}
else {
callback(@[[NSNull null], [resp base64EncodedStringWithOptions:0]]);
}
self.respData = nil;
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}];
[task resume];
respData = [[NSMutableData alloc] init];
respFile = NO;
}
NSURLSessionDataTask * task = [session dataTaskWithRequest:req];
[task resume];

// network status indicator
if([[options objectForKey:CONFIG_INDICATOR] boolValue] == YES)
Expand All @@ -169,19 +124,34 @@ - (void) sendRequest:(NSDictionary * _Nullable )options bridge:(RCTBridge * _Nu
- (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
expectedBytes = [response expectedContentLength];

if(respFile == YES)
{
NSFileManager * fm = [NSFileManager defaultManager];
NSString * folder = [destPath stringByDeletingLastPathComponent];
if(![fm fileExistsAtPath:folder]) {
[fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:nil];
}
[fm createFileAtPath:destPath contents:[[NSData alloc] init] attributes:nil];
writeStream = [[NSOutputStream alloc] initToFileAtPath:destPath append:YES];
[writeStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[writeStream open];
}
completionHandler(NSURLSessionResponseAllow);
}

// download progress handler
- (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
receivedBytes += [data length];

Boolean fileCache = [self.options valueForKey:CONFIG_USE_TEMP];
NSString * path = [self.options valueForKey:CONFIG_FILE_PATH];
// cache data in memory
if(path == nil && fileCache == nil) {
if(respFile == NO)
{
[respData appendData:data];
}
else
{
[writeStream write:[data bytes] maxLength:[data length]];
}

[self.bridge.eventDispatcher
sendDeviceEventWithName:@"RNFetchBlobProgress"
Expand All @@ -191,6 +161,20 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
@"total": [NSString stringWithFormat:@"%d", expectedBytes]
}
];

if(receivedBytes >= expectedBytes)
{
if(respFile == YES)
{
[writeStream close];
callback(@[[NSNull null], destPath]);
}
// base64 response
else {
callback(@[[NSNull null], [respData base64EncodedStringWithOptions:0]]);
}
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
}

- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
Expand All @@ -202,14 +186,12 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCom
// upload progress handler
- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesWritten totalBytesExpectedToSend:(int64_t)totalBytesExpectedToWrite
{
expectedBytes = totalBytesExpectedToWrite;
receivedBytes += totalBytesWritten;
[self.bridge.eventDispatcher
sendDeviceEventWithName:@"RNFetchBlobProgress"
body:@{
@"taskId": taskId,
@"written": [NSString stringWithFormat:@"%d", receivedBytes],
@"total": [NSString stringWithFormat:@"%d", expectedBytes]
@"written": [NSString stringWithFormat:@"%d", totalBytesWritten],
@"total": [NSString stringWithFormat:@"%d", totalBytesExpectedToWrite]
}
];
}
Expand All @@ -230,13 +212,34 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSen
// }
//}

- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
- (void) URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable credantial))completionHandler
{
if([options valueForKey:CONFIG_TRUSTY] != nil)
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
else {
RCTLogWarn(@"counld not create connection with an unstrusted SSL certification, if you're going to create connection anyway, add `trusty:true` to RNFetchBlob.config");
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
{
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
else
{
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
__block NSURLCredential *credential = nil;
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
if (credential) {
disposition = NSURLSessionAuthChallengeUseCredential;
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
}
else
{
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
RCTLogWarn(@"counld not create connection with an unstrusted SSL certification, if you're going to create connection anyway, add `trusty:true` to RNFetchBlob.config");
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
if (completionHandler) {
completionHandler(disposition, credential);
}
}
}

Expand Down

0 comments on commit 1b2d9a7

Please sign in to comment.