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

Commit 1b2d9a7

Browse files
committed
Fix NSURLSession progress report issue #37
1 parent ea478fa commit 1b2d9a7

File tree

2 files changed

+93
-90
lines changed

2 files changed

+93
-90
lines changed

src/ios/RNFetchBlobNetwork.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
typedef void(^CompletionHander)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error);
1616
typedef void(^DataTaskCompletionHander) (NSData * _Nullable resp, NSURLResponse * _Nullable response, NSError * _Nullable error);
1717

18-
@interface RNFetchBlobNetwork : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, UIApplicationDelegate>
18+
@interface RNFetchBlobNetwork : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
1919

2020
@property (nullable, nonatomic) NSString * taskId;
2121
@property (nonatomic) int expectedBytes;
@@ -25,8 +25,8 @@ typedef void(^DataTaskCompletionHander) (NSData * _Nullable resp, NSURLResponse
2525
@property (nullable, nonatomic) RCTBridge * bridge;
2626
@property (nullable, nonatomic) NSDictionary * options;
2727
@property (nullable, nonatomic) RNFetchBlobFS * fileStream;
28-
//@property (strong, nonatomic) CompletionHander fileTaskCompletionHandler;
29-
//@property (strong, nonatomic) DataTaskCompletionHander dataTaskCompletionHandler;
28+
@property (strong, nonatomic) CompletionHander fileTaskCompletionHandler;
29+
@property (strong, nonatomic) DataTaskCompletionHander dataTaskCompletionHandler;
3030
@property (nullable, nonatomic) NSError * error;
3131

3232

src/ios/RNFetchBlobNetwork.m

+90-87
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@
2121
//
2222
////////////////////////////////////////
2323

24+
@interface RNFetchBlobNetwork ()
25+
{
26+
BOOL * respFile;
27+
NSString * destPath;
28+
NSOutputStream * writeStream;
29+
long bodyLength;
30+
}
31+
32+
@end
33+
2434
@implementation RNFetchBlobNetwork
2535

2636
NSOperationQueue *taskQueue;
@@ -32,8 +42,8 @@ @implementation RNFetchBlobNetwork
3242
@synthesize callback;
3343
@synthesize bridge;
3444
@synthesize options;
35-
//@synthesize fileTaskCompletionHandler;
36-
//@synthesize dataTaskCompletionHandler;
45+
@synthesize fileTaskCompletionHandler;
46+
@synthesize dataTaskCompletionHandler;
3747
@synthesize error;
3848

3949

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

86+
bodyLength = [[req HTTPBody] length];
87+
7688
// the session trust any SSL certification
77-
if([options valueForKey:CONFIG_TRUSTY] != nil)
89+
90+
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:taskId];
91+
session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];
92+
93+
if(path != nil || [self.options valueForKey:CONFIG_USE_TEMP]!= nil)
7894
{
79-
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
80-
session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];
95+
respFile = YES;
96+
if(path != nil)
97+
destPath = path;
98+
else
99+
destPath = [RNFetchBlobFS getTempPath:taskId withExtension:[self.options valueForKey:CONFIG_FILE_EXT]];
81100
}
82-
// the session validates SSL certification, self-signed certification will be aborted
83101
else
84102
{
85-
session = [NSURLSession sharedSession];
86-
}
87-
88-
// file will be stored at a specific path
89-
if( path != nil) {
90-
91-
// self.fileTaskCompletionHandler = ;
92-
NSURLSessionDownloadTask * task = [session downloadTaskWithRequest:req completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
93-
if(error != nil) {
94-
callback(@[[error localizedDescription]]);
95-
return;
96-
}
97-
NSError * taskErr;
98-
NSFileManager * fm = [NSFileManager defaultManager];
99-
// move temp file to desination
100-
[fm moveItemAtURL:location toURL:[NSURL fileURLWithPath:path] error:&taskErr];
101-
if(taskErr != nil) {
102-
callback(@[[taskErr localizedDescription]]);
103-
return;
104-
}
105-
callback(@[[NSNull null], path]);
106-
// prevent memory leaks
107-
self.respData = nil;
108-
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
109-
}];
110-
[task resume];
111-
}
112-
// file will be stored at tmp path
113-
else if ( [self.options valueForKey:CONFIG_USE_TEMP]!= nil ) {
114-
115-
// self.fileTaskCompletionHandler;
116-
NSURLSessionDownloadTask * task = [session downloadTaskWithRequest:req completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
117-
if(error != nil) {
118-
callback(@[[error localizedDescription]]);
119-
return;
120-
}
121-
NSError * taskErr;
122-
NSFileManager * fm = [NSFileManager defaultManager];
123-
NSString * tmpPath = [RNFetchBlobFS getTempPath:self.taskId withExtension:[self.options valueForKey:CONFIG_FILE_EXT]];
124-
// move temp file to desination
125-
[fm moveItemAtURL:location toURL:[NSURL fileURLWithPath:tmpPath] error:&taskErr];
126-
if(taskErr != nil) {
127-
callback(@[[taskErr localizedDescription]]);
128-
return;
129-
}
130-
callback(@[[NSNull null], tmpPath]);
131-
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
132-
// prevent memory leaks
133-
self.respData = nil;
134-
}];
135-
[task resume];
136-
}
137-
// base64 response
138-
else {
139-
// self.dataTaskCompletionHandler = ;
140-
NSURLSessionDataTask * task = [session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable resp, NSURLResponse * _Nullable response, NSError * _Nullable error) {
141-
if(error != nil) {
142-
callback(@[[error localizedDescription]]);
143-
return;
144-
}
145-
else {
146-
callback(@[[NSNull null], [resp base64EncodedStringWithOptions:0]]);
147-
}
148-
self.respData = nil;
149-
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
150-
}];
151-
[task resume];
103+
respData = [[NSMutableData alloc] init];
104+
respFile = NO;
152105
}
106+
NSURLSessionDataTask * task = [session dataTaskWithRequest:req];
107+
[task resume];
153108

154109
// network status indicator
155110
if([[options objectForKey:CONFIG_INDICATOR] boolValue] == YES)
@@ -169,19 +124,34 @@ - (void) sendRequest:(NSDictionary * _Nullable )options bridge:(RCTBridge * _Nu
169124
- (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
170125
{
171126
expectedBytes = [response expectedContentLength];
127+
128+
if(respFile == YES)
129+
{
130+
NSFileManager * fm = [NSFileManager defaultManager];
131+
NSString * folder = [destPath stringByDeletingLastPathComponent];
132+
if(![fm fileExistsAtPath:folder]) {
133+
[fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:nil];
134+
}
135+
[fm createFileAtPath:destPath contents:[[NSData alloc] init] attributes:nil];
136+
writeStream = [[NSOutputStream alloc] initToFileAtPath:destPath append:YES];
137+
[writeStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
138+
[writeStream open];
139+
}
140+
completionHandler(NSURLSessionResponseAllow);
172141
}
173142

174143
// download progress handler
175144
- (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
176145
{
177146
receivedBytes += [data length];
178-
179-
Boolean fileCache = [self.options valueForKey:CONFIG_USE_TEMP];
180-
NSString * path = [self.options valueForKey:CONFIG_FILE_PATH];
181-
// cache data in memory
182-
if(path == nil && fileCache == nil) {
147+
if(respFile == NO)
148+
{
183149
[respData appendData:data];
184150
}
151+
else
152+
{
153+
[writeStream write:[data bytes] maxLength:[data length]];
154+
}
185155

186156
[self.bridge.eventDispatcher
187157
sendDeviceEventWithName:@"RNFetchBlobProgress"
@@ -191,6 +161,20 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
191161
@"total": [NSString stringWithFormat:@"%d", expectedBytes]
192162
}
193163
];
164+
165+
if(receivedBytes >= expectedBytes)
166+
{
167+
if(respFile == YES)
168+
{
169+
[writeStream close];
170+
callback(@[[NSNull null], destPath]);
171+
}
172+
// base64 response
173+
else {
174+
callback(@[[NSNull null], [respData base64EncodedStringWithOptions:0]]);
175+
}
176+
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
177+
}
194178
}
195179

196180
- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
@@ -202,14 +186,12 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCom
202186
// upload progress handler
203187
- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesWritten totalBytesExpectedToSend:(int64_t)totalBytesExpectedToWrite
204188
{
205-
expectedBytes = totalBytesExpectedToWrite;
206-
receivedBytes += totalBytesWritten;
207189
[self.bridge.eventDispatcher
208190
sendDeviceEventWithName:@"RNFetchBlobProgress"
209191
body:@{
210192
@"taskId": taskId,
211-
@"written": [NSString stringWithFormat:@"%d", receivedBytes],
212-
@"total": [NSString stringWithFormat:@"%d", expectedBytes]
193+
@"written": [NSString stringWithFormat:@"%d", totalBytesWritten],
194+
@"total": [NSString stringWithFormat:@"%d", totalBytesExpectedToWrite]
213195
}
214196
];
215197
}
@@ -230,13 +212,34 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSen
230212
// }
231213
//}
232214

233-
- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
215+
- (void) URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable credantial))completionHandler
234216
{
235217
if([options valueForKey:CONFIG_TRUSTY] != nil)
236-
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
237-
else {
238-
RCTLogWarn(@"counld not create connection with an unstrusted SSL certification, if you're going to create connection anyway, add `trusty:true` to RNFetchBlob.config");
239-
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
218+
{
219+
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
220+
}
221+
else
222+
{
223+
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
224+
__block NSURLCredential *credential = nil;
225+
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
226+
{
227+
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
228+
if (credential) {
229+
disposition = NSURLSessionAuthChallengeUseCredential;
230+
} else {
231+
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
232+
}
233+
}
234+
else
235+
{
236+
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
237+
RCTLogWarn(@"counld not create connection with an unstrusted SSL certification, if you're going to create connection anyway, add `trusty:true` to RNFetchBlob.config");
238+
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
239+
}
240+
if (completionHandler) {
241+
completionHandler(disposition, credential);
242+
}
240243
}
241244
}
242245

0 commit comments

Comments
 (0)