Browse Source

Add progress report support for IOS #1

Ben Hsieh 8 years ago
parent
commit
5b04a2a250

+ 10
- 5
src/index.js View File

3
  * @version 0.3.3
3
  * @version 0.3.3
4
  */
4
  */
5
 
5
 
6
-import { NativeModules } from 'react-native'
7
-import { DeviceEventEmitter } from 'react-native';
8
-import base64 from 'base-64'
6
+import {
7
+  NativeModules,
8
+  DeviceEventEmitter,
9
+  NativeAppEventEmitter,
10
+  Platform,
11
+} from 'react-native'
9
 
12
 
13
+import base64 from 'base-64'
14
+const emitter = (Platform.OS === 'android' ? DeviceEventEmitter : NativeAppEventEmitter)
10
 const RNFetchBlob = NativeModules.RNFetchBlob
15
 const RNFetchBlob = NativeModules.RNFetchBlob
11
 
16
 
12
 // Show warning if native module not detected
17
 // Show warning if native module not detected
27
 
32
 
28
     let [method, url, headers, body] = [...args]
33
     let [method, url, headers, body] = [...args]
29
     let nativeMethodName = Array.isArray(body) ? 'fetchBlobForm' : 'fetchBlob'
34
     let nativeMethodName = Array.isArray(body) ? 'fetchBlobForm' : 'fetchBlob'
30
-    let handle = DeviceEventEmitter.addListener('RNFetchBlobProgress', (e) => {
35
+    let subscription = emitter.addListener('RNFetchBlobProgress', (e) => {
31
       if(e.taskId === taskId && promise.onProgress) {
36
       if(e.taskId === taskId && promise.onProgress) {
32
         promise.onProgress(e.written, e.total)
37
         promise.onProgress(e.written, e.total)
33
       }
38
       }
36
     RNFetchBlob[nativeMethodName](taskId, method, url, headers || {}, body, (err, ...data) => {
41
     RNFetchBlob[nativeMethodName](taskId, method, url, headers || {}, body, (err, ...data) => {
37
 
42
 
38
       // task done, remove event listener
43
       // task done, remove event listener
39
-      handle.remove()
44
+      subscription.remove()
40
 
45
 
41
       if(err)
46
       if(err)
42
         reject(new Error(err, ...data))
47
         reject(new Error(err, ...data))

+ 41
- 5
src/ios/RNFetchBlob.xcodeproj/project.pbxproj View File

5
 	};
5
 	};
6
 	objectVersion = 46;
6
 	objectVersion = 46;
7
 	objects = {
7
 	objects = {
8
+
8
 /* Begin PBXBuildFile section */
9
 /* Begin PBXBuildFile section */
9
 		A15C30141CD25C330074CB35 /* RNFetchBlob.m in Sources */ = {isa = PBXBuildFile; fileRef = A15C30131CD25C330074CB35 /* RNFetchBlob.m */; };
10
 		A15C30141CD25C330074CB35 /* RNFetchBlob.m in Sources */ = {isa = PBXBuildFile; fileRef = A15C30131CD25C330074CB35 /* RNFetchBlob.m */; };
10
 		A166D1AA1CE0647A00273590 /* RNFetchBlob.h in Sources */ = {isa = PBXBuildFile; fileRef = A15C30111CD25C330074CB35 /* RNFetchBlob.h */; };
11
 		A166D1AA1CE0647A00273590 /* RNFetchBlob.h in Sources */ = {isa = PBXBuildFile; fileRef = A15C30111CD25C330074CB35 /* RNFetchBlob.h */; };
11
 /* End PBXBuildFile section */
12
 /* End PBXBuildFile section */
12
 
13
 
14
+/* Begin PBXContainerItemProxy section */
15
+		A1BAA89E1CF415DF003A9374 /* PBXContainerItemProxy */ = {
16
+			isa = PBXContainerItemProxy;
17
+			containerPortal = ADC1D945EE804D3DA47CF622 /* RNFetchBlob.xcodeproj */;
18
+			proxyType = 2;
19
+			remoteGlobalIDString = A15C300E1CD25C330074CB35;
20
+			remoteInfo = RNFetchBlob;
21
+		};
22
+/* End PBXContainerItemProxy section */
23
+
13
 /* Begin PBXCopyFilesBuildPhase section */
24
 /* Begin PBXCopyFilesBuildPhase section */
14
 		A15C300C1CD25C330074CB35 /* CopyFiles */ = {
25
 		A15C300C1CD25C330074CB35 /* CopyFiles */ = {
15
 			isa = PBXCopyFilesBuildPhase;
26
 			isa = PBXCopyFilesBuildPhase;
26
 		A15C300E1CD25C330074CB35 /* libRNFetchBlob.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFetchBlob.a; sourceTree = BUILT_PRODUCTS_DIR; };
37
 		A15C300E1CD25C330074CB35 /* libRNFetchBlob.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFetchBlob.a; sourceTree = BUILT_PRODUCTS_DIR; };
27
 		A15C30111CD25C330074CB35 /* RNFetchBlob.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNFetchBlob.h; path = RNFetchBlob/RNFetchBlob.h; sourceTree = "<group>"; };
38
 		A15C30111CD25C330074CB35 /* RNFetchBlob.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNFetchBlob.h; path = RNFetchBlob/RNFetchBlob.h; sourceTree = "<group>"; };
28
 		A15C30131CD25C330074CB35 /* RNFetchBlob.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RNFetchBlob.m; path = RNFetchBlob/RNFetchBlob.m; sourceTree = "<group>"; };
39
 		A15C30131CD25C330074CB35 /* RNFetchBlob.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RNFetchBlob.m; path = RNFetchBlob/RNFetchBlob.m; sourceTree = "<group>"; };
29
-		ADC1D945EE804D3DA47CF622 /* RNFetchBlob.xcodeproj */ = {isa = PBXFileReference; name = "RNFetchBlob.xcodeproj"; path = "../../node_modules/react-native-fetch-blob/ios/RNFetchBlob.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; };
40
+		ADC1D945EE804D3DA47CF622 /* RNFetchBlob.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNFetchBlob.xcodeproj; path = "../../node_modules/react-native-fetch-blob/ios/RNFetchBlob.xcodeproj"; sourceTree = "<group>"; };
30
 /* End PBXFileReference section */
41
 /* End PBXFileReference section */
31
 
42
 
32
 /* Begin PBXFrameworksBuildPhase section */
43
 /* Begin PBXFrameworksBuildPhase section */
40
 /* End PBXFrameworksBuildPhase section */
51
 /* End PBXFrameworksBuildPhase section */
41
 
52
 
42
 /* Begin PBXGroup section */
53
 /* Begin PBXGroup section */
54
+		8BD9ABDFAF76406291A798F2 /* Libraries */ = {
55
+			isa = PBXGroup;
56
+			children = (
57
+				ADC1D945EE804D3DA47CF622 /* RNFetchBlob.xcodeproj */,
58
+			);
59
+			name = Libraries;
60
+			sourceTree = "<group>";
61
+		};
43
 		A15C30051CD25C330074CB35 = {
62
 		A15C30051CD25C330074CB35 = {
44
 			isa = PBXGroup;
63
 			isa = PBXGroup;
45
 			children = (
64
 			children = (
58
 			name = Products;
77
 			name = Products;
59
 			sourceTree = "<group>";
78
 			sourceTree = "<group>";
60
 		};
79
 		};
61
-		8BD9ABDFAF76406291A798F2 /* Libraries */ = {
80
+		A1BAA8981CF415DF003A9374 /* Products */ = {
62
 			isa = PBXGroup;
81
 			isa = PBXGroup;
63
 			children = (
82
 			children = (
64
-				ADC1D945EE804D3DA47CF622 /* RNFetchBlob.xcodeproj */,
83
+				A1BAA89F1CF415DF003A9374 /* libRNFetchBlob.a */,
65
 			);
84
 			);
66
-			name = Libraries;
67
-			path = "";
85
+			name = Products;
68
 			sourceTree = "<group>";
86
 			sourceTree = "<group>";
69
 		};
87
 		};
70
 /* End PBXGroup section */
88
 /* End PBXGroup section */
111
 			mainGroup = A15C30051CD25C330074CB35;
129
 			mainGroup = A15C30051CD25C330074CB35;
112
 			productRefGroup = A15C300F1CD25C330074CB35 /* Products */;
130
 			productRefGroup = A15C300F1CD25C330074CB35 /* Products */;
113
 			projectDirPath = "";
131
 			projectDirPath = "";
132
+			projectReferences = (
133
+				{
134
+					ProductGroup = A1BAA8981CF415DF003A9374 /* Products */;
135
+					ProjectRef = ADC1D945EE804D3DA47CF622 /* RNFetchBlob.xcodeproj */;
136
+				},
137
+			);
114
 			projectRoot = "";
138
 			projectRoot = "";
115
 			targets = (
139
 			targets = (
116
 				A15C300D1CD25C330074CB35 /* RNFetchBlob */,
140
 				A15C300D1CD25C330074CB35 /* RNFetchBlob */,
118
 		};
142
 		};
119
 /* End PBXProject section */
143
 /* End PBXProject section */
120
 
144
 
145
+/* Begin PBXReferenceProxy section */
146
+		A1BAA89F1CF415DF003A9374 /* libRNFetchBlob.a */ = {
147
+			isa = PBXReferenceProxy;
148
+			fileType = archive.ar;
149
+			path = libRNFetchBlob.a;
150
+			remoteRef = A1BAA89E1CF415DF003A9374 /* PBXContainerItemProxy */;
151
+			sourceTree = BUILT_PRODUCTS_DIR;
152
+		};
153
+/* End PBXReferenceProxy section */
154
+
121
 /* Begin PBXSourcesBuildPhase section */
155
 /* Begin PBXSourcesBuildPhase section */
122
 		A15C300A1CD25C330074CB35 /* Sources */ = {
156
 		A15C300A1CD25C330074CB35 /* Sources */ = {
123
 			isa = PBXSourcesBuildPhase;
157
 			isa = PBXSourcesBuildPhase;
225
 					"$(SRCROOT)/../../react-native/React/**",
259
 					"$(SRCROOT)/../../react-native/React/**",
226
 					"$(SRCROOT)/../../node_modules/react-native/React/**",
260
 					"$(SRCROOT)/../../node_modules/react-native/React/**",
227
 					"$(SRCROOT)/../../node_modules/react-native-fetch-blob/ios/RNFetchBlob",
261
 					"$(SRCROOT)/../../node_modules/react-native-fetch-blob/ios/RNFetchBlob",
262
+					"$(SRCROOT)/../../RNFetchBlobTest/node_modules/react-native/**",
228
 				);
263
 				);
229
 				OTHER_LDFLAGS = "-ObjC";
264
 				OTHER_LDFLAGS = "-ObjC";
230
 				PRODUCT_NAME = "$(TARGET_NAME)";
265
 				PRODUCT_NAME = "$(TARGET_NAME)";
244
 					"$(SRCROOT)/../../react-native/React/**",
279
 					"$(SRCROOT)/../../react-native/React/**",
245
 					"$(SRCROOT)/../../node_modules/react-native/React/**",
280
 					"$(SRCROOT)/../../node_modules/react-native/React/**",
246
 					"$(SRCROOT)/../../node_modules/react-native-fetch-blob/ios/RNFetchBlob",
281
 					"$(SRCROOT)/../../node_modules/react-native-fetch-blob/ios/RNFetchBlob",
282
+					"$(SRCROOT)/../../RNFetchBlobTest/node_modules/react-native/**",
247
 				);
283
 				);
248
 				OTHER_LDFLAGS = "-ObjC";
284
 				OTHER_LDFLAGS = "-ObjC";
249
 				PRODUCT_NAME = "$(TARGET_NAME)";
285
 				PRODUCT_NAME = "$(TARGET_NAME)";

+ 23
- 5
src/ios/RNFetchBlob/RNFetchBlob.h View File

1
 //
1
 //
2
 //  RNFetchBlob.h
2
 //  RNFetchBlob.h
3
 //
3
 //
4
-//  Created by suzuri04x2 on 2016/4/28.
5
-//  Copyright © 2016年 Facebook. All rights reserved.
4
+//  Created by wkh237 on 2016/4/28.
6
 //
5
 //
7
 
6
 
8
 #ifndef RNFetchBlob_h
7
 #ifndef RNFetchBlob_h
9
 #define RNFetchBlob_h
8
 #define RNFetchBlob_h
10
-
9
+#import <Foundation/Foundation.h>
11
 #import "RCTBridgeModule.h"
10
 #import "RCTBridgeModule.h"
12
 
11
 
13
 @interface RNFetchBlob : NSObject <RCTBridgeModule> 
12
 @interface RNFetchBlob : NSObject <RCTBridgeModule> 
14
 
13
 
15
 @end
14
 @end
16
 
15
 
17
-@interface FetchBlobUtils : NSObject
16
+@interface FetchBlobUtils : NSObject  <NSURLConnectionDelegate, NSURLConnectionDataDelegate> {
17
+
18
+    NSString * taskId;
19
+    int expectedBytes;
20
+    int receivedBytes;
21
+    NSMutableData * respData;
22
+    RCTResponseSenderBlock callback;
23
+    RCTBridge * bridge;
24
+}
25
+@property (nonatomic) NSString * taskId;
26
+@property (nonatomic) int expectedBytes;
27
+@property (nonatomic) int receivedBytes;
28
+@property (nonatomic) NSMutableData * respData;
29
+@property (nonatomic) RCTResponseSenderBlock callback;
30
+@property (nonatomic) RCTBridge * bridge;
31
+
32
+
33
+- (id) init;
34
+- (id) delegate;
35
+- (void) sendRequest;
18
 
36
 
19
-+ (void) onBlobResponse;
20
 + (NSMutableDictionary *) normalizeHeaders;
37
 + (NSMutableDictionary *) normalizeHeaders;
21
 
38
 
39
+
22
 @end
40
 @end
23
 
41
 
24
 
42
 

+ 118
- 34
src/ios/RNFetchBlob/RNFetchBlob.m View File

2
 //  RNFetchBlob.m
2
 //  RNFetchBlob.m
3
 //
3
 //
4
 //  Created by suzuri04x2 on 2016/4/28.
4
 //  Created by suzuri04x2 on 2016/4/28.
5
-//  Copyright © 2016年 Facebook. All rights reserved.
6
 //
5
 //
7
 
6
 
8
 #import "RNFetchBlob.h"
7
 #import "RNFetchBlob.h"
9
 #import "RCTConvert.h"
8
 #import "RCTConvert.h"
10
 #import "RCTLog.h"
9
 #import "RCTLog.h"
11
 #import <Foundation/Foundation.h>
10
 #import <Foundation/Foundation.h>
11
+#import "RCTBridge.h"
12
+#import "RCTEventDispatcher.h"
12
 
13
 
13
 
14
 
14
 ////////////////////////////////////////
15
 ////////////////////////////////////////
19
 
20
 
20
 @implementation FetchBlobUtils
21
 @implementation FetchBlobUtils
21
 
22
 
22
-// callback class method to handle request
23
-+ (void) onBlobResponse:(NSURLResponse * _Nullable)response withData:(NSData * _Nullable)data withError:(NSError * _Nullable)connectionError withCallback:(RCTResponseSenderBlock)callback{
24
-    
25
-    NSHTTPURLResponse* resp = (NSHTTPURLResponse *) response;
26
-    NSString* status = [NSString stringWithFormat:@"%d", resp.statusCode];
27
-    
28
-    if(connectionError)
29
-    {
30
-        callback(@[[connectionError localizedDescription], [NSNull null]]);
31
-    }
32
-    else if(![status isEqualToString:@"200"]) {
33
-        callback(@[status, [NSNull null]]);
34
-    }
35
-    else {
36
-        callback(@[[NSNull null], [data base64EncodedStringWithOptions:0]]);
37
-    }
38
-    
39
-}
23
+
24
+@synthesize taskId;
25
+@synthesize expectedBytes;
26
+@synthesize receivedBytes;
27
+@synthesize respData;
28
+@synthesize callback;
29
+@synthesize bridge;
30
+
40
 
31
 
41
 // removing case of headers
32
 // removing case of headers
42
 + (NSMutableDictionary *) normalizeHeaders:(NSDictionary *)headers {
33
 + (NSMutableDictionary *) normalizeHeaders:(NSDictionary *)headers {
49
     return mheaders;
40
     return mheaders;
50
 }
41
 }
51
 
42
 
43
+- (id)init {
44
+    self = [super init];
45
+    return self;
46
+}
47
+
48
+- (id)delegate:(id)delegate {
49
+    return delegate;
50
+}
51
+
52
+- (void) sendRequest:(RCTBridge *)bridgeRef taskId:(NSString *)taskId withRequest:(NSURLRequest *)req callback:(RCTResponseSenderBlock) callback {
53
+    self.taskId = taskId;
54
+    self.respData = [[NSMutableData alloc] initWithLength:0];
55
+    self.callback = callback;
56
+    self.bridge = bridgeRef;
57
+    // Call long-running code on background thread
58
+    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:NO];
59
+    [conn scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
60
+    [conn start];
61
+    
62
+    if(!conn) {
63
+        callback(@[[NSString stringWithFormat:@"RNFetchBlob could not initialize connection"], [NSNull null]]);
64
+    }
65
+}
66
+
67
+
68
+#pragma mark NSURLConnection delegate methods
69
+
70
+
71
+- (void) connection:(NSURLConnection *)connection didReceiveResponse:(nonnull NSURLResponse *)response {
72
+    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
73
+    expectedBytes = [response expectedContentLength];
74
+}
75
+
76
+- (void) connection:(NSURLConnection *)connection didReceiveData:(nonnull NSData *)data {
77
+    receivedBytes = data.length;
78
+    [respData appendData:data];
79
+    
80
+    [self.bridge.eventDispatcher
81
+        sendAppEventWithName:@"RNFetchBlobProgress"
82
+        body:@{
83
+            @"taskId": taskId,
84
+            @"written": [NSString stringWithFormat:@"%d", receivedBytes],
85
+            @"total": [NSString stringWithFormat:@"%d", expectedBytes]
86
+        }
87
+     ];
88
+}
89
+
90
+- (void) connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite {
91
+    
92
+    expectedBytes = totalBytesExpectedToWrite;
93
+    receivedBytes = totalBytesWritten;
94
+    [self.bridge.eventDispatcher
95
+        sendAppEventWithName:@"RNFetchBlobProgress"
96
+            body:@{
97
+                    @"taskId": taskId,
98
+                    @"written": [NSString stringWithFormat:@"%d", receivedBytes],
99
+                    @"total": [NSString stringWithFormat:@"%d", expectedBytes]
100
+                }
101
+     ];
102
+    
103
+}
104
+
105
+- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
106
+    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
107
+    callback(@[[error localizedDescription], [NSNull null]]);
108
+}
109
+
110
+- (NSCachedURLResponse *) connection:(NSURLConnection *)connection willCacheResponse: (NSCachedURLResponse *)cachedResponse {
111
+    return nil;
112
+}
113
+
114
+
115
+// handle 301 and 302 responses
116
+- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:response {
117
+    
118
+    return request;
119
+}
120
+
121
+// request complete
122
+- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
123
+    NSData * data = [NSData dataWithData:respData];
124
+    callback(@[[NSNull null], [data base64EncodedStringWithOptions:0]]);
125
+}
126
+
52
 @end
127
 @end
53
 
128
 
54
 
129
 
60
 
135
 
61
 @implementation RNFetchBlob
136
 @implementation RNFetchBlob
62
 
137
 
138
+@synthesize bridge = _bridge;
139
+
63
 RCT_EXPORT_MODULE();
140
 RCT_EXPORT_MODULE();
64
 
141
 
65
 // Fetch blob data request
142
 // Fetch blob data request
66
-RCT_EXPORT_METHOD(fetchBlobForm:(NSString *)method url:(NSString *)url headers:(NSDictionary *)headers form:(NSArray *)form callback:(RCTResponseSenderBlock)callback)
143
+RCT_EXPORT_METHOD(fetchBlobForm:(NSString *)taskId method:(NSString *)method url:(NSString *)url headers:(NSDictionary *)headers form:(NSArray *)form callback:(RCTResponseSenderBlock)callback)
67
 {
144
 {
68
     
145
     
69
     // send request
146
     // send request
70
     NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
147
     NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
71
                                     initWithURL:[NSURL
148
                                     initWithURL:[NSURL
72
                                                  URLWithString: url]];
149
                                                  URLWithString: url]];
150
+    
73
     NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] initWithDictionary:[ FetchBlobUtils normalizeHeaders:headers]];
151
     NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] initWithDictionary:[ FetchBlobUtils normalizeHeaders:headers]];
74
     
152
     
75
     
153
     
120
     [request setHTTPMethod: method];
198
     [request setHTTPMethod: method];
121
     [request setAllHTTPHeaderFields:mheaders];
199
     [request setAllHTTPHeaderFields:mheaders];
122
     
200
     
201
+    [[[FetchBlobUtils alloc] init] sendRequest:self.bridge taskId:taskId withRequest:request callback:callback];
202
+    
123
     // create thread for http request
203
     // create thread for http request
124
-    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
125
-    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
126
-        
127
-        [FetchBlobUtils onBlobResponse:response withData:data withError: connectionError withCallback: callback];
128
-        
129
-    }];
204
+//    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
205
+//    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
206
+//        
207
+//        [FetchBlobUtils onBlobResponse:response withData:data withError: connectionError withCallback: callback];
208
+//        
209
+//    }];
130
     
210
     
131
 }
211
 }
132
 
212
 
133
 // Fetch blob data request
213
 // Fetch blob data request
134
-RCT_EXPORT_METHOD(fetchBlob:(NSString *)method url:(NSString *)url headers:(NSDictionary *)headers body:(NSString *)body callback:(RCTResponseSenderBlock)callback)
214
+RCT_EXPORT_METHOD(fetchBlob:(NSString *)taskId method:(NSString *)method url:(NSString *)url headers:(NSDictionary *)headers body:(NSString *)body callback:(RCTResponseSenderBlock)callback)
135
 {
215
 {
136
     // send request
216
     // send request
137
     NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
217
     NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
155
     [request setHTTPMethod: method];
235
     [request setHTTPMethod: method];
156
     [request setAllHTTPHeaderFields:mheaders];
236
     [request setAllHTTPHeaderFields:mheaders];
157
     
237
     
238
+    [[[FetchBlobUtils alloc] init] sendRequest:self.bridge taskId:taskId withRequest:request callback:callback];
239
+    
158
     // create thread for http request
240
     // create thread for http request
159
-    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
160
-    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
161
-        
162
-        [FetchBlobUtils onBlobResponse:response withData:data withError: connectionError withCallback: callback];
163
-        
164
-    }];
241
+//    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
242
+//    
243
+//    
244
+//    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
245
+//        
246
+//        [FetchBlobUtils onBlobResponse:response withData:data withError: connectionError withCallback: callback];
247
+//        
248
+//    }];
165
     
249
     
166
 }
250
 }
167
-@end
168
 
251
 
252
+@end

+ 44
- 0
src/ios/RNFetchBlobUtil.h View File

1
+//
2
+//  RNFetchBlobUtil.h
3
+//  RNFetchBlob
4
+//
5
+//  Created by Ben Hsieh on 2016/5/24.
6
+//  Copyright © 2016年 suzuri04x2. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+#import "RCTBridgeModule.h"
11
+
12
+#ifndef RNFetchBlobUtil_h
13
+#define RNFetchBlobUtil_h
14
+
15
+@class FetchBlobUtils;
16
+
17
+
18
+@interface FetchBlobUtils : NSObject  <RCTBridgeModule, NSURLConnectionDelegate, NSURLConnectionDataDelegate> {
19
+    
20
+    NSString * taskId;
21
+    int expectedBytes;
22
+    int receivedBytes;
23
+    NSMutableData * respData;
24
+    RCTResponseSenderBlock callback;
25
+}
26
+@property (nonatomic) NSString * taskId;
27
+@property (nonatomic) int expectedBytes;
28
+@property (nonatomic) int receivedBytes;
29
+@property (nonatomic) NSMutableData * respData;
30
+@property (nonatomic) RCTResponseSenderBlock callback;
31
+
32
+
33
+- (id) init;
34
+- (id) delegate;
35
+- (void) sendRequest;
36
+
37
++ (NSMutableDictionary *) normalizeHeaders;
38
+
39
+
40
+@end
41
+
42
+
43
+
44
+#endif /* RNFetchBlobUtil_h */

+ 140
- 0
src/ios/RNFetchBlobUtil.m View File

1
+//
2
+//  RNFetchBlobUtil.m
3
+//  RNFetchBlob
4
+//
5
+//  Created by Ben Hsieh on 2016/5/24.
6
+//  Copyright © 2016年 suzuri04x2. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+#import "RNFetchBlobUtil.h"
11
+
12
+
13
+////////////////////////////////////////
14
+//
15
+//  Util functions
16
+//
17
+////////////////////////////////////////
18
+
19
+@implementation FetchBlobUtils
20
+
21
+
22
+@synthesize taskId;
23
+@synthesize expectedBytes;
24
+@synthesize receivedBytes;
25
+@synthesize respData;
26
+@synthesize callback;
27
+
28
+RCT_EXPORT_MODULE();
29
+
30
+// callback class method to handle request
31
+//+ (void) onBlobResponse:(NSURLResponse * _Nullable)response withData:(NSData * _Nullable)data withError:(NSError * _Nullable)connectionError withCallback:(RCTResponseSenderBlock) callback{
32
+//
33
+//    NSHTTPURLResponse* resp = (NSHTTPURLResponse *) response;
34
+//    NSString* status = [NSString stringWithFormat:@"%d", resp.statusCode];
35
+//
36
+//    if(connectionError)
37
+//    {
38
+//        callback(@[[connectionError localizedDescription], [NSNull null]]);
39
+//    }
40
+//    else if(![status isEqualToString:@"200"]) {
41
+//        callback(@[status, [NSNull null]]);
42
+//    }
43
+//    else {
44
+//        callback(@[[NSNull null], [data base64EncodedStringWithOptions:0]]);
45
+//    }
46
+//
47
+//}
48
+
49
+// removing case of headers
50
++ (NSMutableDictionary *) normalizeHeaders:(NSDictionary *)headers {
51
+    
52
+    NSMutableDictionary * mheaders = [[NSMutableDictionary alloc]init];
53
+    for(NSString * key in headers) {
54
+        [mheaders setValue:[headers valueForKey:key] forKey:[key lowercaseString]];
55
+    }
56
+    
57
+    return mheaders;
58
+}
59
+
60
+- (id)init {
61
+    self = [super init];
62
+    return self;
63
+}
64
+
65
+- (id)delegate:(id)delegate {
66
+    return delegate;
67
+}
68
+
69
+- (void) sendRequest:(NSString *)taskId withRequest:(NSURLRequest *)req callback:(RCTResponseSenderBlock) callback {
70
+    self.taskId = taskId;
71
+    self.respData = [[NSMutableData alloc] initWithLength:0];
72
+    // Call long-running code on background thread
73
+    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:NO];
74
+    [conn scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
75
+    [conn start];
76
+    
77
+    if(!conn) {
78
+        callback(@[[NSString stringWithFormat:@"RNFetchBlob could not initialize connection"], [NSNull null]]);
79
+    }
80
+}
81
+
82
+
83
+#pragma mark NSURLConnection delegate methods
84
+
85
+
86
+- (void) connection:(NSURLConnection *)connection didReceiveResponse:(nonnull NSURLResponse *)response {
87
+    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
88
+    expectedBytes = [response expectedContentLength];
89
+}
90
+
91
+- (void) connection:(NSURLConnection *)connection didReceiveData:(nonnull NSData *)data {
92
+    receivedBytes = data.length;
93
+    [respData appendData:data];
94
+    [self.bridge.eventDispatcher
95
+     sendAppEventWithName:@"RNFetchBlobProgress"
96
+     body:@{
97
+            @"taskId": taskId,
98
+            @"written": [NSString stringWithFormat:@"%@", receivedBytes],
99
+            @"total": [NSString stringWithFormat:@"%@", expectedBytes]
100
+            }
101
+     ];
102
+}
103
+
104
+- (void) connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite {
105
+    
106
+    expectedBytes = totalBytesExpectedToWrite;
107
+    receivedBytes = totalBytesWritten;
108
+    [self.bridge.eventDispatcher
109
+     sendAppEventWithName:@"RNFetchBlobProgress"
110
+     body:@{
111
+            @"taskId": taskId,
112
+            @"written": [NSString stringWithFormat:@"%@", receivedBytes],
113
+            @"total": [NSString stringWithFormat:@"%@", expectedBytes]
114
+            }
115
+     ];
116
+    
117
+}
118
+
119
+- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
120
+    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
121
+    callback(@[[error localizedDescription], [NSNull null]]);
122
+}
123
+
124
+- (NSCachedURLResponse *) connection:(NSURLConnection *)connection willCacheResponse: (NSCachedURLResponse *)cachedResponse {
125
+    return nil;
126
+}
127
+
128
+
129
+// handle 301 and 302 responses
130
+- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:response {
131
+    
132
+    return request;
133
+}
134
+
135
+// request complete
136
+- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
137
+    callback(@[[NSNull null], [respData base64EncodedStringWithOptions:0]]);
138
+}
139
+
140
+@end