Browse Source

Fix IOS ALAsset upload issue #45

Ben Hsieh 8 years ago
parent
commit
23eee765d6

+ 6
- 0
src/ios/RNFetchBlob.xcodeproj/project.pbxproj View File

@@ -12,6 +12,7 @@
12 12
 		A158F4301D0539DB006FFD38 /* RNFetchBlobNetwork.m in Sources */ = {isa = PBXBuildFile; fileRef = A158F42F1D0539DB006FFD38 /* RNFetchBlobNetwork.m */; };
13 13
 		A15C30141CD25C330074CB35 /* RNFetchBlob.m in Sources */ = {isa = PBXBuildFile; fileRef = A15C30131CD25C330074CB35 /* RNFetchBlob.m */; };
14 14
 		A166D1AA1CE0647A00273590 /* RNFetchBlob.h in Sources */ = {isa = PBXBuildFile; fileRef = A15C30111CD25C330074CB35 /* RNFetchBlob.h */; };
15
+		A1AAE2991D300E4D0051D11C /* RNFetchBlobReqBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = A1AAE2981D300E4D0051D11C /* RNFetchBlobReqBuilder.m */; };
15 16
 /* End PBXBuildFile section */
16 17
 
17 18
 /* Begin PBXCopyFilesBuildPhase section */
@@ -36,6 +37,8 @@
36 37
 		A15C300E1CD25C330074CB35 /* libRNFetchBlob.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFetchBlob.a; sourceTree = BUILT_PRODUCTS_DIR; };
37 38
 		A15C30111CD25C330074CB35 /* RNFetchBlob.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNFetchBlob.h; path = RNFetchBlob/RNFetchBlob.h; sourceTree = "<group>"; };
38 39
 		A15C30131CD25C330074CB35 /* RNFetchBlob.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RNFetchBlob.m; path = RNFetchBlob/RNFetchBlob.m; sourceTree = "<group>"; };
40
+		A1AAE2971D300E3E0051D11C /* RNFetchBlobReqBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNFetchBlobReqBuilder.h; sourceTree = "<group>"; };
41
+		A1AAE2981D300E4D0051D11C /* RNFetchBlobReqBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFetchBlobReqBuilder.m; sourceTree = "<group>"; };
39 42
 /* End PBXFileReference section */
40 43
 
41 44
 /* Begin PBXFrameworksBuildPhase section */
@@ -59,6 +62,8 @@
59 62
 		A15C30051CD25C330074CB35 = {
60 63
 			isa = PBXGroup;
61 64
 			children = (
65
+				A1AAE2981D300E4D0051D11C /* RNFetchBlobReqBuilder.m */,
66
+				A1AAE2971D300E3E0051D11C /* RNFetchBlobReqBuilder.h */,
62 67
 				A158F42F1D0539DB006FFD38 /* RNFetchBlobNetwork.m */,
63 68
 				A158F42E1D0539CE006FFD38 /* RNFetchBlobNetwork.h */,
64 69
 				A158F42C1D0535BB006FFD38 /* RNFetchBlobConst.m */,
@@ -140,6 +145,7 @@
140 145
 				A158F42D1D0535BB006FFD38 /* RNFetchBlobConst.m in Sources */,
141 146
 				A158F4271D052E49006FFD38 /* RNFetchBlobFS.m in Sources */,
142 147
 				A158F4301D0539DB006FFD38 /* RNFetchBlobNetwork.m in Sources */,
148
+				A1AAE2991D300E4D0051D11C /* RNFetchBlobReqBuilder.m in Sources */,
143 149
 				A15C30141CD25C330074CB35 /* RNFetchBlob.m in Sources */,
144 150
 			);
145 151
 			runOnlyForDeploymentPostprocessing = 0;

+ 11
- 114
src/ios/RNFetchBlob/RNFetchBlob.m View File

@@ -12,6 +12,7 @@
12 12
 #import "RNFetchBlobFS.h"
13 13
 #import "RNFetchBlobNetwork.h"
14 14
 #import "RNFetchBlobConst.h"
15
+#import "RNFetchBlobReqBuilder.h"
15 16
 
16 17
 
17 18
 ////////////////////////////////////////
@@ -61,78 +62,14 @@ RCT_EXPORT_METHOD(fetchBlobForm:(NSDictionary *)options
61 62
                   form:(NSArray *)form
62 63
                   callback:(RCTResponseSenderBlock)callback)
63 64
 {
64
-    NSString * encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
65
-    // send request
66
-    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
67
-                                    initWithURL:[NSURL
68
-                                                 URLWithString: encodedUrl]];
69 65
     
70
-    NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] initWithDictionary:[ RNFetchBlobNetwork normalizeHeaders:headers]];
71
-    
72
-    
73
-    NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
74
-    NSNumber * timeStampObj = [NSNumber numberWithDouble: timeStamp];
75
-    
76
-    // generate boundary
77
-    NSString * boundary = [NSString stringWithFormat:@"RNFetchBlob%d", timeStampObj];
78
-    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
79
-        NSMutableData * postData = [[NSMutableData alloc] init];
80
-        // if method is POST or PUT, convert data string format
81
-        if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
82
-            
83
-            // combine multipart/form-data body
84
-            for(id field in form) {
85
-                NSString * name = [field valueForKey:@"name"];
86
-                NSString * content = [field valueForKey:@"data"];
87
-                // field is a text field
88
-                if([field valueForKey:@"filename"] == nil || content == [NSNull null]) {
89
-                    [postData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
90
-                    [postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", name] dataUsingEncoding:NSUTF8StringEncoding]];
91
-                    [postData appendData:[[NSString stringWithFormat:@"Content-Type: text/plain\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
92
-                    [postData appendData:[[NSString stringWithFormat:@"%@\r\n", content] dataUsingEncoding:NSUTF8StringEncoding]];
93
-                }
94
-                // field contains a file
95
-                else {
96
-                    NSMutableData * blobData;
97
-                    if(content != nil) {
98
-                        if([content hasPrefix:self.filePathPrefix]) {
99
-                            NSString * orgPath = [content substringFromIndex:[self.filePathPrefix length]];
100
-                            orgPath = [RNFetchBlobFS getPathOfAsset:orgPath];
101
-                            blobData = [[NSData alloc] initWithContentsOfFile:orgPath];
102
-                        }
103
-                        else
104
-                            blobData = [[NSData alloc] initWithBase64EncodedString:content options:0];
105
-                    }
106
-                    NSString * filename = [field valueForKey:@"filename"];
107
-                    [postData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
108
-                    [postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", name, filename] dataUsingEncoding:NSUTF8StringEncoding]];
109
-                    [postData appendData:[[NSString stringWithFormat:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
110
-                    [postData appendData:blobData];
111
-                    [postData appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
112
-                }
113
-                
114
-            }
115
-            
116
-            // close form data
117
-            [postData appendData: [[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
118
-            [request setHTTPBody:postData];
119
-            // set content-length
120
-            [mheaders setValue:[NSString stringWithFormat:@"%d",[postData length]] forKey:@"Content-Length"];
121
-            [mheaders setValue:[NSString stringWithFormat:@"100-continue",[postData length]] forKey:@"Expect"];
122
-            // appaned boundary to content-type
123
-            [mheaders setValue:[NSString stringWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@", boundary] forKey:@"content-type"];
124
-            
125
-        }
126
-        
127
-        [request setHTTPMethod: method];
128
-        [request setAllHTTPHeaderFields:mheaders];
129
-        
130
-        
66
+    [RNFetchBlobReqBuilder buildMultipartRequest:options taskId:taskId method:method url:url headers:headers form:form onComplete:^(NSURLRequest *req) {
131 67
         // send HTTP request
132 68
         RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init];
133
-        [utils sendRequest:options bridge:self.bridge taskId:taskId withRequest:request callback:callback];
69
+        [utils sendRequest:options bridge:self.bridge taskId:taskId withRequest:req callback:callback];
134 70
         utils = nil;
135
-    });
71
+    }];
72
+    
136 73
 }
137 74
 
138 75
 // Fetch blob data request
@@ -143,46 +80,13 @@ RCT_EXPORT_METHOD(fetchBlob:(NSDictionary *)options
143 80
                   headers:(NSDictionary *)headers
144 81
                   body:(NSString *)body callback:(RCTResponseSenderBlock)callback)
145 82
 {
146
-    NSString * encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
147
-    // send request
148
-    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
149
-                                    initWithURL:[NSURL
150
-                                                 URLWithString: encodedUrl]];
151
-    
152
-    NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] initWithDictionary:[RNFetchBlobNetwork normalizeHeaders:headers]];
153
-    // move heavy task to another thread
154
-    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
155
-        NSMutableData * blobData;
156
-        // if method is POST or PUT, convert data string format
157
-        if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
158
-            // generate octet-stream body
159
-            if(body != nil) {
160
-                
161
-                // when body is a string contains file path prefix, try load file from the path
162
-                if([body hasPrefix:self.filePathPrefix]) {
163
-                    NSString * orgPath = [body substringFromIndex:[self.filePathPrefix length]];
164
-                    orgPath = [RNFetchBlobFS getPathOfAsset:orgPath];
165
-                    [request setHTTPBodyStream: [NSInputStream inputStreamWithFileAtPath:orgPath ]];
166
-                }
167
-                // otherwise convert it as BASE64 data string
168
-                else {
169
-                    blobData = [[NSData alloc] initWithBase64EncodedString:body options:0];
170
-                    [request setHTTPBody:blobData];
171
-                }
172
-                
173
-                [mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
174
-                
175
-            }
176
-        }
177
-        
178
-        [request setHTTPMethod: method];
179
-        [request setAllHTTPHeaderFields:mheaders];
180
-        
83
+    [RNFetchBlobReqBuilder buildOctetRequest:options taskId:taskId method:method url:url headers:headers body:body onComplete:^(NSURLRequest *req) {
181 84
         // send HTTP request
182 85
         RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init];
183
-        [utils sendRequest:options bridge:self.bridge taskId:taskId withRequest:request callback:callback];
86
+        [utils sendRequest:options bridge:self.bridge taskId:taskId withRequest:req callback:callback];
184 87
         utils = nil;
185
-    });
88
+    }];
89
+    
186 90
 }
187 91
 
188 92
 RCT_EXPORT_METHOD(createFile:(NSString *)path data:(NSString *)data encoding:(NSString *)encoding callback:(RCTResponseSenderBlock)callback) {
@@ -419,7 +323,7 @@ RCT_EXPORT_METHOD(mkdir:(NSString *)path callback:(RCTResponseSenderBlock) callb
419 323
 
420 324
 RCT_EXPORT_METHOD(readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
421 325
     
422
-    [RNFetchBlobFS readFile:path encoding:encoding resolver:resolve rejecter:reject];
326
+    [RNFetchBlobFS readFile:path encoding:encoding resolver:resolve rejecter:reject onComplete:nil];
423 327
 })
424 328
 
425 329
 RCT_EXPORT_METHOD(readStream:(NSString *)path withEncoding:(NSString *)encoding bufferSize:(int)bufferSize) {
@@ -432,14 +336,7 @@ RCT_EXPORT_METHOD(readStream:(NSString *)path withEncoding:(NSString *)encoding
432 336
             bufferSize = 4096;
433 337
     }
434 338
     // read asset stream
435
-    if([path hasPrefix:@"assets-library://"])
436
-    {
437
-        
438
-    }
439
-    else
440
-    {
441
-        [fileStream readWithPath:path useEncoding:encoding bufferSize:bufferSize];
442
-    }
339
+    [fileStream readWithPath:path useEncoding:encoding bufferSize:bufferSize];
443 340
 }
444 341
 
445 342
 RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback) {

+ 3
- 0
src/ios/RNFetchBlobConst.h View File

@@ -16,7 +16,10 @@ extern NSString *const MSG_EVENT;
16 16
 extern NSString *const MSG_EVENT_LOG;
17 17
 extern NSString *const MSG_EVENT_WARN;
18 18
 extern NSString *const MSG_EVENT_ERROR;
19
+
19 20
 extern NSString *const FILE_PREFIX;
21
+extern NSString *const ASSET_PREFIX;
22
+extern NSString *const AL_PREFIX;
20 23
 
21 24
 // config
22 25
 extern NSString *const CONFIG_USE_TEMP;

+ 4
- 0
src/ios/RNFetchBlobConst.m View File

@@ -8,6 +8,10 @@
8 8
 #import "RNFetchBlobConst.h"
9 9
 
10 10
 extern NSString *const FILE_PREFIX = @"RNFetchBlob-file://";
11
+extern NSString *const ASSET_PREFIX = @"bundle-assets://";
12
+extern NSString *const AL_PREFIX = @"assets-library://";
13
+
14
+
11 15
 
12 16
 // fetch configs
13 17
 extern NSString *const CONFIG_USE_TEMP = @"fileCache";

+ 4
- 2
src/ios/RNFetchBlobFS.h View File

@@ -11,6 +11,7 @@
11 11
 
12 12
 #import <Foundation/Foundation.h>
13 13
 #import "RCTBridgeModule.h"
14
+@import AssetsLibrary;
14 15
 
15 16
 @interface RNFetchBlobFS : NSObject <NSStreamDelegate>  {
16 17
     NSOutputStream * outStream;
@@ -42,6 +43,8 @@
42 43
 + (NSString *) getCacheDir;
43 44
 + (NSString *) getDocumentDir;
44 45
 + (NSString *) getTempPath:(NSString*)taskId withExtension:(NSString *)ext;
46
++ (NSString *) getPathOfAsset:(NSString *)assetURI;
47
++ (void) getPathFromUri:(NSString *)uri completionHandler:(void(^)(NSString * path, ALAssetRepresentation *asset)) onComplete;
45 48
 
46 49
 // fs methods
47 50
 + (RNFetchBlobFS *) getFileStreams;
@@ -50,9 +53,8 @@
50 53
 + (BOOL) exists:(NSString *) path;
51 54
 + (void) writeFileArray:(NSString *)path data:(NSArray *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
52 55
 + (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
53
-+ (void) readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
56
++ (void) readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject onComplete:(void (^)(NSData * content))onComplete;
54 57
 + (void) readAssetFile:(NSData *)assetUrl completionBlock:(void(^)(NSData * content))completionBlock failBlock:(void(^)(NSError * err))failBlock;
55
-+ (NSString *) getPathOfAsset:(NSString *)assetURI;
56 58
 
57 59
 // constructor
58 60
 - (id) init;

+ 72
- 86
src/ios/RNFetchBlobFS.m View File

@@ -15,7 +15,7 @@
15 15
 #import "RNFetchBlobFS.h"
16 16
 #import "RNFetchBlobConst.h"
17 17
 @import AssetsLibrary;
18
-@import Photos;
18
+
19 19
 
20 20
 NSMutableDictionary *fileStreams = nil;
21 21
 
@@ -54,9 +54,9 @@ NSMutableDictionary *fileStreams = nil;
54 54
 +(NSString *) getPathOfAsset:(NSString *)assetURI
55 55
 {
56 56
     // get file path of an app asset
57
-    if([assetURI hasPrefix:@"bundle-assets://"])
57
+    if([assetURI hasPrefix:ASSET_PREFIX])
58 58
     {
59
-        assetURI = [assetURI stringByReplacingOccurrencesOfString:@"bundle-assets://" withString:@""];
59
+        assetURI = [assetURI stringByReplacingOccurrencesOfString:ASSET_PREFIX withString:@""];
60 60
         assetURI = [[NSBundle mainBundle] pathForResource: [assetURI stringByDeletingPathExtension]
61 61
                                                ofType: [assetURI pathExtension]];
62 62
     }
@@ -98,7 +98,7 @@ NSMutableDictionary *fileStreams = nil;
98 98
     return tempPath;
99 99
 }
100 100
 
101
-- (void) startAssetReadStream:(NSData *)assetUrl
101
+- (void) startAssetReadStream:(NSString *)assetUrl
102 102
 {
103 103
     ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
104 104
     {
@@ -185,34 +185,6 @@ NSMutableDictionary *fileStreams = nil;
185 185
     }
186 186
 }
187 187
 
188
-// read system asset file
189
-+ (void) readAssetFile:(NSData *)assetUrl completionBlock:(void(^)(NSData * content))completionBlock failBlock:(void(^)(NSError * err))failBlock
190
-{
191
-    
192
-    ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
193
-    {
194
-        ALAssetRepresentation *rep = [myasset defaultRepresentation];
195
-        Byte *buffer = (Byte*)malloc(rep.size);
196
-        NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
197
-        NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
198
-        completionBlock(data);
199
-    };
200
-    
201
-    ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *error)
202
-    {
203
-        failBlock(error);
204
-    };
205
-    
206
-    if(assetUrl && [assetUrl length])
207
-    {
208
-        NSURL *asseturl = [NSURL URLWithString:assetUrl];
209
-        ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
210
-        [assetslibrary assetForURL:asseturl
211
-                       resultBlock:resultblock
212
-                      failureBlock:failureblock];
213
-    }
214
-}
215
-
216 188
 + (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
217 189
     @try {
218 190
         NSFileManager * fm = [NSFileManager defaultManager];
@@ -301,68 +273,62 @@ NSMutableDictionary *fileStreams = nil;
301 273
     }
302 274
 }
303 275
 
304
-+ (void) readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
276
++ (void) readFile:(NSString *)path encoding:(NSString *)encoding
277
+         resolver:(RCTPromiseResolveBlock)resolve
278
+         rejecter:(RCTPromiseRejectBlock)reject
279
+       onComplete:(void (^)(NSData * content))onComplete
280
+{
305 281
     @try
306 282
     {
307
-        // before start reading file, we have to check if the `path` contains any special prefix
308
-        // if the `path` begins with the following prefix then it will need special handling.
309
-        //      "assets-library://" this kind of path usually comes from camera roll, should use it's own readFile implementation
310
-        //      "bundle-assets://" this means an asset inside app bundle, usually we only have to convert it into normal file path
311
-        if([path hasPrefix:@"assets-library://"])
312
-        {
313
-            [[self class] readAssetFile:path completionBlock:^(NSData * content)
283
+        [[self class] getPathFromUri:path completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
284
+            NSData * fileContent;
285
+            NSError * err;
286
+            if(asset != nil)
287
+            {
288
+                Byte * buffer = malloc(asset.size);
289
+                [asset getBytes:buffer fromOffset:0 length:asset.size error:&err];
290
+                if(err != nil)
291
+                {
292
+                    reject(@"RNFetchBlobFS readFile error", @"failed to read asset", [err localizedDescription]);
293
+                    return;
294
+                }
295
+                fileContent = [NSData dataWithBytes:buffer length:asset.size];
296
+                if(onComplete != nil)
297
+                    onComplete(fileContent);
298
+                free(buffer);
299
+            }
300
+            else
314 301
             {
315
-                if([[encoding lowercaseString] isEqualToString:@"utf8"]) {
316
-                    resolve([[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding]);
302
+                BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path];
303
+                if(!exists) {
304
+                    reject(@"RNFetchBlobFS readFile error", @"file not exists", path);
305
+                    return;
317 306
                 }
318
-                else if ([[encoding lowercaseString] isEqualToString:@"base64"]) {
319
-                    resolve([content base64EncodedStringWithOptions:0]);
307
+                fileContent = [NSData dataWithContentsOfFile:path];
308
+            }
309
+            
310
+            if([[encoding lowercaseString] isEqualToString:@"utf8"]) {
311
+                if(resolve != nil)
312
+                    resolve([[NSString alloc] initWithData:fileContent encoding:NSUTF8StringEncoding]);
313
+            }
314
+            else if ([[encoding lowercaseString] isEqualToString:@"base64"]) {
315
+                if(resolve != nil)
316
+                    resolve([fileContent base64EncodedStringWithOptions:0]);
317
+            }
318
+            else if ([[encoding lowercaseString] isEqualToString:@"ascii"]) {
319
+                NSMutableArray * resultArray = [NSMutableArray array];
320
+                char * bytes = [fileContent bytes];
321
+                for(int i=0;i<[fileContent length];i++) {
322
+                    [resultArray addObject:[NSNumber numberWithChar:bytes[i]]];
320 323
                 }
321
-                else if ([[encoding lowercaseString] isEqualToString:@"ascii"]) {
322
-                    NSMutableArray * resultArray = [NSMutableArray array];
323
-                    char * bytes = [content bytes];
324
-                    for(int i=0;i<[content length];i++) {
325
-                        [resultArray addObject:[NSNumber numberWithChar:bytes[i]]];
326
-                    }
324
+                if(resolve != nil)
327 325
                     resolve(resultArray);
328
-                }
329
-            } failBlock:^(NSError *err) {
330
-                @throw @"RNFetchBlobFS readFile error", @"failed to read asset", path;
331
-            }];
332
-            return ;
333
-        }
334
-        
335
-        // normalize the file path
336
-        path = [[self class]getPathOfAsset:path];
337
-        
338
-        NSFileManager * fm = [NSFileManager defaultManager];
339
-        NSError *err = nil;
340
-        BOOL exists = [fm fileExistsAtPath:path];
341
-        if(!exists) {
342
-            @throw @"RNFetchBlobFS readFile error", @"file not exists", path;
343
-            return;
344
-        }
345
-        if([[encoding lowercaseString] isEqualToString:@"utf8"]) {
346
-            NSString * utf8Result = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err];
347
-            resolve(utf8Result);
348
-        }
349
-        else if ([[encoding lowercaseString] isEqualToString:@"base64"]) {
350
-            NSData * fileData = [NSData dataWithContentsOfFile:path];
351
-            resolve([fileData base64EncodedStringWithOptions:0]);
352
-        }
353
-        else if ([[encoding lowercaseString] isEqualToString:@"ascii"]) {
354
-            NSData * resultData = [NSData dataWithContentsOfFile:path];
355
-            NSMutableArray * resultArray = [NSMutableArray array];
356
-            char * bytes = [resultData bytes];
357
-            for(int i=0;i<[resultData length];i++) {
358
-                [resultArray addObject:[NSNumber numberWithChar:bytes[i]]];
359 326
             }
360
-            resolve(resultArray);
361
-        }
362
-
327
+        }];
363 328
     }
364 329
     @catch(NSException * e)
365 330
     {
331
+        if(reject != nil)
366 332
         reject(@"RNFetchBlobFS readFile error", @"error", [e description]);
367 333
     }
368 334
 }
@@ -486,9 +452,9 @@ NSMutableDictionary *fileStreams = nil;
486 452
     self.path = path;
487 453
     self.bufferSize = bufferSize;
488 454
     
489
-    if([path hasPrefix:@"assets-library://"])
455
+    if([path hasPrefix:AL_PREFIX])
490 456
     {
491
-     
457
+        [self startAssetReadStream:path];
492 458
         return;
493 459
     }
494 460
     
@@ -631,4 +597,24 @@ NSMutableDictionary *fileStreams = nil;
631 597
 
632 598
 }
633 599
 
600
++ (void) getPathFromUri:(NSString *)uri completionHandler:(void(^)(NSString * path, ALAssetRepresentation *asset)) onComplete
601
+{
602
+    if([uri hasPrefix:AL_PREFIX])
603
+    {
604
+        NSURL *asseturl = [NSURL URLWithString:uri];
605
+        ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
606
+        [assetslibrary assetForURL:asseturl
607
+                       resultBlock:^(ALAsset *asset) {
608
+                           onComplete(nil, [asset defaultRepresentation]);
609
+                       }
610
+                      failureBlock:^(NSError *error) {
611
+                          onComplete(nil, nil);
612
+                      }];
613
+    }
614
+    else
615
+    {
616
+        onComplete([[self class] getPathOfAsset:uri], nil);
617
+    }
618
+}
619
+
634 620
 @end

+ 1
- 0
src/ios/RNFetchBlobNetwork.h View File

@@ -11,6 +11,7 @@
11 11
 
12 12
 #import <Foundation/Foundation.h>
13 13
 #import "RCTBridgeModule.h"
14
+#import "RNFetchBlobFS.h"
14 15
 
15 16
 typedef void(^CompletionHander)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error);
16 17
 typedef void(^DataTaskCompletionHander) (NSData * _Nullable resp, NSURLResponse * _Nullable response, NSError * _Nullable error);

+ 34
- 0
src/ios/RNFetchBlobReqBuilder.h View File

@@ -0,0 +1,34 @@
1
+//
2
+//  RNFetchBlobReqBuilder.h
3
+//  RNFetchBlob
4
+//
5
+//  Created by Ben Hsieh on 2016/7/9.
6
+//  Copyright © 2016年 wkh237. All rights reserved.
7
+//
8
+
9
+#ifndef RNFetchBlobReqBuilder_h
10
+#define RNFetchBlobReqBuilder_h
11
+
12
+#import <Foundation/Foundation.h>
13
+
14
+@interface RNFetchBlobReqBuilder : NSObject;
15
+
16
++(void) buildMultipartRequest:(NSDictionary *)options
17
+                       taskId:(NSString *)taskId
18
+                       method:(NSString *)method
19
+                          url:(NSString *)url
20
+                      headers:(NSDictionary *)headers
21
+                         form:(NSArray *)form
22
+                   onComplete:(void(^)(NSURLRequest * req))onComplete;
23
+
24
++(void) buildOctetRequest:(NSDictionary *)options
25
+                   taskId:(NSString *)taskId
26
+                   method:(NSString *)method
27
+                      url:(NSString *)url
28
+                  headers:(NSDictionary *)headers
29
+                     body:(NSString *)body
30
+               onComplete:(void(^)(NSURLRequest * req))onComplete;
31
+
32
+@end
33
+
34
+#endif /* RNFetchBlobReqBuilder_h */

+ 195
- 0
src/ios/RNFetchBlobReqBuilder.m View File

@@ -0,0 +1,195 @@
1
+//
2
+//  RNFetchBlobReqBuilder.m
3
+//  RNFetchBlob
4
+//
5
+//  Created by Ben Hsieh on 2016/7/9.
6
+//  Copyright © 2016年 wkh237. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+#import "RNFetchBlobReqBuilder.h"
11
+#import "RNFetchBlobNetwork.h"
12
+#import "RNFetchBlobConst.h"
13
+#import "RNFetchBlobFS.h"
14
+
15
+@interface RNFetchBlobReqBuilder()
16
+{
17
+    
18
+}
19
+@end
20
+
21
+@implementation RNFetchBlobReqBuilder
22
+
23
+
24
+// Fetch blob data request
25
++(void) buildMultipartRequest:(NSDictionary *)options
26
+                       taskId:(NSString *)taskId
27
+                       method:(NSString *)method
28
+                          url:(NSString *)url
29
+                      headers:(NSDictionary *)headers
30
+                         form:(NSArray *)form
31
+                   onComplete:(void(^)(NSURLRequest * req))onComplete
32
+{
33
+    NSString * encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
34
+    // send request
35
+    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString: encodedUrl]];
36
+    NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] initWithDictionary:[RNFetchBlobNetwork normalizeHeaders:headers]];
37
+    NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
38
+    NSNumber * timeStampObj = [NSNumber numberWithDouble: timeStamp];
39
+    
40
+    // generate boundary
41
+    NSString * boundary = [NSString stringWithFormat:@"RNFetchBlob%d", timeStampObj];
42
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
43
+        NSMutableData * postData = [[NSMutableData alloc] init];
44
+        // combine multipart/form-data body
45
+        [[self class] buildFormBody:form boundary:boundary onComplete:^(NSData *formData) {
46
+            if(formData != nil) {
47
+                [postData appendData:formData];
48
+                // close form data
49
+                [postData appendData: [[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
50
+                [request setHTTPBody:postData];
51
+            }
52
+            // set content-length
53
+            [mheaders setValue:[NSString stringWithFormat:@"%d",[postData length]] forKey:@"Content-Length"];
54
+            [mheaders setValue:[NSString stringWithFormat:@"100-continue",[postData length]] forKey:@"Expect"];
55
+            // appaned boundary to content-type
56
+            [mheaders setValue:[NSString stringWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@", boundary] forKey:@"content-type"];
57
+            [request setHTTPMethod: method];
58
+            [request setAllHTTPHeaderFields:mheaders];
59
+            onComplete(request);
60
+        }];
61
+        
62
+    });
63
+}
64
+
65
+// Fetch blob data request
66
++(void) buildOctetRequest:(NSDictionary *)options
67
+                   taskId:(NSString *)taskId
68
+                   method:(NSString *)method
69
+                      url:(NSString *)url
70
+                  headers:(NSDictionary *)headers
71
+                     body:(NSString *)body
72
+               onComplete:(void(^)(NSURLRequest * req))onComplete
73
+{
74
+    NSString * encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
75
+    // send request
76
+    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
77
+                                    initWithURL:[NSURL
78
+                                                 URLWithString: encodedUrl]];
79
+    
80
+    NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] initWithDictionary:[RNFetchBlobNetwork normalizeHeaders:headers]];
81
+    // move heavy task to another thread
82
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
83
+        NSMutableData * blobData;
84
+        // if method is POST or PUT, convert data string format
85
+        if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
86
+            // generate octet-stream body
87
+            if(body != nil) {
88
+                
89
+                // when body is a string contains file path prefix, try load file from the path
90
+                if([body hasPrefix:FILE_PREFIX]) {
91
+                    NSString * orgPath = [body substringFromIndex:[FILE_PREFIX length]];
92
+                    orgPath = [RNFetchBlobFS getPathOfAsset:orgPath];
93
+                    if([orgPath hasPrefix:AL_PREFIX])
94
+                    {
95
+                        [RNFetchBlobFS readFile:orgPath encoding:@"utf8" resolver:nil rejecter:nil onComplete:^(NSData *content) {
96
+                            [request setHTTPBody:content];
97
+                            [mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
98
+                            [request setHTTPMethod: method];
99
+                            [request setAllHTTPHeaderFields:mheaders];
100
+                            onComplete(request);
101
+                        }];
102
+                        return;
103
+                    }
104
+                    [request setHTTPBodyStream: [NSInputStream inputStreamWithFileAtPath:orgPath ]];
105
+                }
106
+                // otherwise convert it as BASE64 data string
107
+                else {
108
+                    blobData = [[NSData alloc] initWithBase64EncodedString:body options:0];
109
+                    [request setHTTPBody:blobData];
110
+                }
111
+                
112
+                [mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
113
+                
114
+            }
115
+        }
116
+        
117
+        [request setHTTPMethod: method];
118
+        [request setAllHTTPHeaderFields:mheaders];
119
+        
120
+        onComplete(request);
121
+    });
122
+}
123
+
124
++(void) buildFormBody:(NSArray *)form boundary:(NSString *)boundary onComplete:(void(^)(NSData * formData))onComplete
125
+{
126
+    NSMutableData * formData = [[NSMutableData alloc] init];
127
+    if(form == nil)
128
+        onComplete(nil);
129
+    else
130
+    {
131
+        __block int i = 0;
132
+        __block int count = [form count];
133
+        void __block (^getFieldData)(id field) = ^(id field)
134
+        {
135
+            NSString * name = [field valueForKey:@"name"];
136
+            NSString * content = [field valueForKey:@"data"];
137
+            // field is a text field
138
+            if([field valueForKey:@"filename"] == nil || content == [NSNull null]) {
139
+                [formData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
140
+                [formData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", name] dataUsingEncoding:NSUTF8StringEncoding]];
141
+                [formData appendData:[[NSString stringWithFormat:@"Content-Type: text/plain\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
142
+                [formData appendData:[[NSString stringWithFormat:@"%@\r\n", content] dataUsingEncoding:NSUTF8StringEncoding]];
143
+            }
144
+            // field contains a file
145
+            else {
146
+                NSMutableData * blobData;
147
+                if(content != nil)
148
+                {
149
+                    // append data from file asynchronously
150
+                    if([content hasPrefix:FILE_PREFIX])
151
+                    {
152
+                        NSString * orgPath = [content substringFromIndex:[FILE_PREFIX length]];
153
+                        orgPath = [RNFetchBlobFS getPathOfAsset:orgPath];
154
+                        [RNFetchBlobFS readFile:orgPath encoding:@"utf8" resolver:nil rejecter:nil onComplete:^(NSData *content) {
155
+                            NSString * filename = [field valueForKey:@"filename"];
156
+                            [formData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
157
+                            [formData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", name, filename] dataUsingEncoding:NSUTF8StringEncoding]];
158
+                            [formData appendData:[[NSString stringWithFormat:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
159
+                            [formData appendData:content];
160
+                            [formData appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
161
+                            i++;
162
+                            if(i < count)
163
+                            {
164
+                                getFieldData([form objectAtIndex:i]);
165
+                            }
166
+                            else
167
+                                onComplete(formData);
168
+                        }];
169
+                        return ;
170
+                    }
171
+                    else
172
+                        blobData = [[NSData alloc] initWithBase64EncodedString:content options:0];
173
+                }
174
+                NSString * filename = [field valueForKey:@"filename"];
175
+                [formData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
176
+                [formData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", name, filename] dataUsingEncoding:NSUTF8StringEncoding]];
177
+                [formData appendData:[[NSString stringWithFormat:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
178
+                [formData appendData:blobData];
179
+                [formData appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
180
+            }
181
+            i++;
182
+            if(i < count)
183
+            {
184
+                getFieldData([form objectAtIndex:i]);
185
+            }
186
+            else
187
+                onComplete(formData);
188
+            
189
+        };
190
+        getFieldData([form objectAtIndex:i]);
191
+    }
192
+}
193
+
194
+
195
+@end