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
2636NSOperationQueue *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