Преглед на файлове

#24 Change IOS fetch implementation to NSURLSession API

Ben Hsieh преди 8 години
родител
ревизия
e612ea5d58
променени са 3 файла, в които са добавени 122 реда и са изтрити 81 реда
  1. 4
    4
      src/ios/RNFetchBlob/RNFetchBlob.m
  2. 2
    2
      src/ios/RNFetchBlobResp.h
  3. 116
    75
      src/ios/RNFetchBlobResp.m

+ 4
- 4
src/ios/RNFetchBlob/RNFetchBlob.m Целия файл

@@ -76,9 +76,9 @@ RCT_EXPORT_METHOD(fetchBlobForm:(NSDictionary *)options
76 76
     // generate boundary
77 77
     NSString * boundary = [NSString stringWithFormat:@"RNFetchBlob%d", timeStampObj];
78 78
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
79
+        NSMutableData * postData = [[NSMutableData alloc] init];
79 80
         // if method is POST or PUT, convert data string format
80 81
         if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
81
-            NSMutableData * postData = [[NSMutableData alloc] init];
82 82
             
83 83
             // combine multipart/form-data body
84 84
             for(id field in form) {
@@ -129,7 +129,7 @@ RCT_EXPORT_METHOD(fetchBlobForm:(NSDictionary *)options
129 129
         
130 130
         // send HTTP request
131 131
         FetchBlobUtils * utils = [[FetchBlobUtils alloc] init];
132
-        [utils sendRequest:options bridge:self.bridge taskId:taskId withRequest:request callback:callback];
132
+        [utils sendRequest:options bridge:self.bridge taskId:taskId withRequest:request withData:postData callback:callback];
133 133
     });
134 134
 }
135 135
 
@@ -149,11 +149,11 @@ RCT_EXPORT_METHOD(fetchBlob:(NSDictionary *)options
149 149
     NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] initWithDictionary:[FetchBlobUtils normalizeHeaders:headers]];
150 150
     // move heavy task to another thread
151 151
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
152
+        NSMutableData * blobData;
152 153
         // if method is POST or PUT, convert data string format
153 154
         if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
154 155
             // generate octet-stream body
155 156
             if(body != nil) {
156
-                NSMutableData * blobData;
157 157
                 
158 158
                 // when body is a string contains file path prefix, try load file from the path
159 159
                 if([body hasPrefix:self.filePathPrefix]) {
@@ -174,7 +174,7 @@ RCT_EXPORT_METHOD(fetchBlob:(NSDictionary *)options
174 174
         
175 175
         // send HTTP request
176 176
         FetchBlobUtils * utils = [[FetchBlobUtils alloc] init];
177
-        [utils sendRequest:options bridge:self.bridge taskId:taskId withRequest:request callback:callback];
177
+        [utils sendRequest:options bridge:self.bridge taskId:taskId withRequest:request withData:blobData callback:callback];
178 178
     });
179 179
 }
180 180
 

+ 2
- 2
src/ios/RNFetchBlobResp.h Целия файл

@@ -12,7 +12,7 @@
12 12
 #import <Foundation/Foundation.h>
13 13
 #import "RCTBridgeModule.h"
14 14
 
15
-@interface FetchBlobUtils : NSObject  <NSURLConnectionDelegate, NSURLConnectionDataDelegate> {
15
+@interface FetchBlobUtils : NSObject  <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate> {
16 16
     
17 17
     NSString * taskId;
18 18
     int expectedBytes;
@@ -37,7 +37,7 @@
37 37
 - (void) sendRequest;
38 38
 
39 39
 + (NSMutableDictionary *) normalizeHeaders:(NSDictionary *)headers;
40
-- (void) sendRequest:(NSDictionary *)options bridge:(RCTBridge *)bridgeRef taskId:(NSString *)taskId withRequest:(NSURLRequest *)req callback:(RCTResponseSenderBlock) callback;
40
+- (void) sendRequest:(NSDictionary *)options bridge:(RCTBridge *)bridgeRef taskId:(NSString *)taskId withRequest:(NSURLRequest *)req withData:( NSData * _Nullable )data callback:(RCTResponseSenderBlock) callback;
41 41
 
42 42
 
43 43
 @end

+ 116
- 75
src/ios/RNFetchBlobResp.m Целия файл

@@ -50,7 +50,7 @@
50 50
 }
51 51
 
52 52
 
53
-- (void) sendRequest:(NSDictionary *)options bridge:(RCTBridge *)bridgeRef taskId:(NSString *)taskId withRequest:(NSURLRequest *)req callback:(RCTResponseSenderBlock) callback {
53
+- (void) sendRequest:(NSDictionary *)options bridge:(RCTBridge *)bridgeRef taskId:(NSString *)taskId withRequest:(NSURLRequest *)req withData:( NSData * _Nullable )data callback:(RCTResponseSenderBlock) callback {
54 54
     self.taskId = taskId;
55 55
     self.respData = [[NSMutableData alloc] initWithLength:0];
56 56
     self.callback = callback;
@@ -61,52 +61,89 @@
61 61
     
62 62
     NSString * path = [self.options valueForKey:CONFIG_FILE_PATH];
63 63
     NSString * ext = [self.options valueForKey:CONFIG_FILE_EXT];
64
+
65
+    NSURLSession * session = [NSURLSession sharedSession];
64 66
     
65
-    // open file stream for write
67
+    // file will be stored at a specific path
66 68
     if( path != nil) {
67
-        self.fileStream = [[RNFetchBlobFS alloc]initWithCallback:self.callback];
68
-        [self.fileStream openWithPath:path encode:@"ascii" appendData:YES ];
69
+        NSURLSessionDownloadTask * task = [session downloadTaskWithRequest:req completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
70
+            if(error != nil) {
71
+                callback(@[[error localizedDescription]]);
72
+                return;
73
+            }
74
+            NSError * taskErr;
75
+            NSFileManager * fm = [NSFileManager defaultManager];
76
+            // move temp file to desination
77
+            [fm moveItemAtURL:location toURL:[NSURL fileURLWithPath:path] error:&taskErr];
78
+            if(taskErr != nil) {
79
+                callback(@[[taskErr localizedDescription]]);
80
+                return;
81
+            }
82
+            callback(@[[NSNull null], path]);
83
+        }];
84
+        [task resume];
69 85
     }
86
+    // file will be stored at tmp path
70 87
     else if ( [self.options valueForKey:CONFIG_USE_TEMP]!= nil ) {
71
-        self.fileStream = [[RNFetchBlobFS alloc]initWithCallback:self.callback];
72
-        [self.fileStream openWithPath:[RNFetchBlobFS getTempPath:taskId withExtension:ext] encode:@"ascii" appendData:YES];
88
+        NSURLSessionDownloadTask * task = [session downloadTaskWithRequest:req completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
89
+            if(error != nil) {
90
+                callback(@[[error localizedDescription]]);
91
+                return;
92
+            }
93
+            NSError * taskErr;
94
+            NSFileManager * fm = [NSFileManager defaultManager];
95
+            NSString * tmpPath = [RNFetchBlobFS getTempPath:self.taskId withExtension:[self.options valueForKey:CONFIG_FILE_EXT]];
96
+            // move temp file to desination
97
+            [fm moveItemAtURL:location toURL:[NSURL fileURLWithPath:tmpPath] error:&taskErr];
98
+            if(taskErr != nil) {
99
+                callback(@[[taskErr localizedDescription]]);
100
+                return;
101
+            }
102
+            callback(@[[NSNull null], tmpPath]);
103
+        }];
104
+        [task resume];
73 105
     }
74
-    
75
-    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:NO];
76
-    [conn scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
77
-    [conn start];
78
-    
79
-    if(!conn) {
80
-        callback(@[[NSString stringWithFormat:@"RNFetchBlob could not initialize connection"], [NSNull null]]);
106
+    // base64 response
107
+    else {
108
+        
109
+        NSURLSessionUploadTask * task =
110
+        [session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable resp, NSURLResponse * _Nullable response, NSError * _Nullable error) {
111
+            if(error != nil) {
112
+                callback(@[[error localizedDescription]]);
113
+                return;
114
+            }
115
+            else
116
+                callback(@[[NSNull null], [resp base64EncodedStringWithOptions:0]]);
117
+        }];
118
+//        [session uploadTaskWithRequest:req fromData:data completionHandler:^(NSData * _Nullable resp, NSURLResponse * _Nullable response, NSError * _Nullable error) {
119
+//            if(error != nil) {
120
+//                callback(@[[error localizedDescription]]);
121
+//                return;
122
+//            }
123
+//            else
124
+//                callback(@[[NSNull null], [resp base64EncodedStringWithOptions:0]]);
125
+//        }];
126
+        [task resume];
81 127
     }
128
+//    callback(@[[NSString stringWithFormat:@"RNFetchBlob could not initialize connection"], [NSNull null]]);
82 129
 }
83 130
 
84 131
 
85
-#pragma mark NSURLConnection delegate methods
132
+#pragma mark NSURLSession delegate methods
86 133
 
87
-
88
-- (void) connection:(NSURLConnection *)connection didReceiveResponse:(nonnull NSURLResponse *)response {
89
-    //    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
134
+- (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
135
+{
90 136
     expectedBytes = [response expectedContentLength];
91 137
 }
92 138
 
93
-
94
-- (void) connection:(NSURLConnection *)connection didReceiveData:(nonnull NSData *)data {
139
+- (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
140
+{
95 141
     receivedBytes += [data length];
96 142
     
97 143
     Boolean fileCache = [self.options valueForKey:CONFIG_USE_TEMP];
98 144
     NSString * path = [self.options valueForKey:CONFIG_FILE_PATH];
99
-    if(path != nil) {
100
-        
101
-        [self.fileStream write:data];
102
-    }
103
-    // write to tmp file
104
-    else if( fileCache != nil) {
105
-        NSString * ext = [self.options valueForKey:CONFIG_FILE_EXT];
106
-        [self.fileStream write:data];
107
-    }
108 145
     // cache data in memory
109
-    else {
146
+    if(path == nil && fileCache == nil) {
110 147
         [respData appendData:data];
111 148
     }
112 149
     
@@ -120,8 +157,8 @@
120 157
      ];
121 158
 }
122 159
 
123
-- (void) connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite {
124
-    
160
+- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesWritten totalBytesExpectedToSend:(int64_t)totalBytesExpectedToWrite
161
+{
125 162
     expectedBytes = totalBytesExpectedToWrite;
126 163
     receivedBytes += totalBytesWritten;
127 164
     [self.bridge.eventDispatcher
@@ -132,57 +169,61 @@
132 169
             @"total": [NSString stringWithFormat:@"%d", expectedBytes]
133 170
             }
134 171
      ];
135
-    
136 172
 }
137 173
 
138
-- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
139
-    
140
-    //    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
141
-    
142
-    [self.fileStream closeInStream];
143
-    [self.fileStream closeOutStream];
144
-    
145
-    callback(@[[error localizedDescription], [NSNull null]]);
146
-}
147 174
 
148
-- (NSCachedURLResponse *) connection:(NSURLConnection *)connection willCacheResponse: (NSCachedURLResponse *)cachedResponse {
149
-    return nil;
150
-}
175
+//- (void) URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
176
+//{
177
+//
178
+//}
179
+
180
+
181
+//- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
182
+//    
183
+//    //    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
184
+//    
185
+//    [self.fileStream closeInStream];
186
+//    [self.fileStream closeOutStream];
187
+//    
188
+//    callback(@[[error localizedDescription], [NSNull null]]);
189
+//}
190
+
191
+
151 192
 
152 193
 
153 194
 // handle 301 and 302 responses
154
-- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:response {
155
-    return request;
156
-}
195
+//- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:response {
196
+//    return request;
197
+//}
157 198
 
158 199
 // request complete
159
-- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
160
-    
161
-    NSData * data;
162
-    if(respData != nil)
163
-        data = [NSData dataWithData:respData];
164
-    else
165
-        data = [[NSData alloc] init];
166
-    
167
-    NSString * path = [self.options valueForKey:CONFIG_FILE_PATH];
168
-    NSString * ext = [self.options valueForKey:CONFIG_FILE_EXT];
169
-    Boolean useCache = [self.options valueForKey:CONFIG_USE_TEMP];
170
-    
171
-    [self.fileStream closeInStream];
172
-    
173
-    // if fileCache is true or file path is given, return a path
174
-    if( path != nil ) {
175
-        callback(@[[NSNull null], path]);
176
-    }
177
-    // when fileCache option is set but no path specified, save to tmp path
178
-    else if( [self.options valueForKey:CONFIG_USE_TEMP] != nil) {
179
-        NSString * tmpPath = [RNFetchBlobFS getTempPath:taskId withExtension:ext];
180
-        callback(@[[NSNull null], tmpPath]);
181
-    }
182
-    // otherwise return base64 string
183
-    else {
184
-        callback(@[[NSNull null], [data base64EncodedStringWithOptions:0]]);
185
-    }
186
-}
200
+//- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
201
+//    
202
+//    NSData * data;
203
+//    if(respData != nil)
204
+//        data = [NSData dataWithData:respData];
205
+//    else
206
+//        data = [[NSData alloc] init];
207
+//    
208
+//    NSString * path = [self.options valueForKey:CONFIG_FILE_PATH];
209
+//    NSString * ext = [self.options valueForKey:CONFIG_FILE_EXT];
210
+//    Boolean useCache = [self.options valueForKey:CONFIG_USE_TEMP];
211
+//    
212
+//    [self.fileStream closeInStream];
213
+//    
214
+//    // if fileCache is true or file path is given, return a path
215
+//    if( path != nil ) {
216
+//        callback(@[[NSNull null], path]);
217
+//    }
218
+//    // when fileCache option is set but no path specified, save to tmp path
219
+//    else if( [self.options valueForKey:CONFIG_USE_TEMP] != nil) {
220
+//        NSString * tmpPath = [RNFetchBlobFS getTempPath:taskId withExtension:ext];
221
+//        callback(@[[NSNull null], tmpPath]);
222
+//    }
223
+//    // otherwise return base64 string
224
+//    else {
225
+//        callback(@[[NSNull null], [data base64EncodedStringWithOptions:0]]);
226
+//    }
227
+//}
187 228
 
188 229
 @end