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

Commit cc088be

Browse files
committed
Add multipart support to ios.
1 parent ab16719 commit cc088be

File tree

3 files changed

+111
-7
lines changed

3 files changed

+111
-7
lines changed

index.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,20 @@ const fetch = (...args) => new Promise((resolve, reject) => {
77

88
let [method, url, headers, body] = [...args]
99

10-
RNFetchBlob.fetchBlob(method, url, headers, body, (err, data) => {
11-
if(err)
12-
reject(new Error(err, data))
13-
else
14-
resolve(new FetchBlobResponse(data))
15-
})
10+
if(Array.isArray(body))
11+
RNFetchBlob.fetchBlobForm(method, url, headers, body, (err, data) => {
12+
if(err)
13+
reject(new Error(err, data))
14+
else
15+
resolve(new FetchBlobResponse(data))
16+
})
17+
else
18+
RNFetchBlob.fetchBlob(method, url, headers, body, (err, data) => {
19+
if(err)
20+
reject(new Error(err, data))
21+
else
22+
resolve(new FetchBlobResponse(data))
23+
})
1624

1725

1826
})

ios/RNFetchBlob/RNFetchBlob.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#import "RCTBridgeModule.h"
1212

1313
@interface RNFetchBlob : NSObject <RCTBridgeModule>
14+
1415
@end
1516

1617

ios/RNFetchBlob/RNFetchBlob.m

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,90 @@ @implementation RNFetchBlob
1515

1616
RCT_EXPORT_MODULE();
1717

18+
// Fetch blob data request
19+
RCT_EXPORT_METHOD(fetchBlobForm:(NSString *)method url:(NSString *)url headers:(NSDictionary *)headers form:(NSArray *)form callback:(RCTResponseSenderBlock)callback)
20+
{
21+
// send request
22+
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
23+
initWithURL:[NSURL
24+
URLWithString: url]];
25+
26+
NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] init];
27+
28+
// make headers case insensitive
29+
for(NSString * key in headers) {
30+
[mheaders setValue:[headers valueForKey:key] forKey:[key lowercaseString]];
31+
}
32+
33+
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
34+
NSNumber * timeStampObj = [NSNumber numberWithDouble: timeStamp];
35+
36+
// generate boundary
37+
NSString * boundary = [NSString stringWithFormat:@"RNFetchBlob%d", timeStampObj];
38+
39+
// if method is POST or PUT, convert data string format
40+
if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
41+
NSMutableData * postData = [[NSMutableData alloc] init];
42+
43+
// combine body
44+
for(id field in form) {
45+
NSString * name = [field valueForKey:@"name"];
46+
NSString * content = [field valueForKey:@"data"];
47+
// field is a text field
48+
if([field valueForKey:@"filename"] == nil) {
49+
[postData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
50+
[postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", name] dataUsingEncoding:NSUTF8StringEncoding]];
51+
[postData appendData:[[NSString stringWithFormat:@"Content-Type: text/plain\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
52+
[postData appendData:[[NSString stringWithFormat:@"%@\r\n", content] dataUsingEncoding:NSUTF8StringEncoding]];
53+
}
54+
// field contains a file
55+
else {
56+
NSData* blobData = [[NSData alloc] initWithBase64EncodedString:content options:0];
57+
NSString * filename = [field valueForKey:@"filename"];
58+
[postData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
59+
[postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", name, filename] dataUsingEncoding:NSUTF8StringEncoding]];
60+
[postData appendData:[[NSString stringWithFormat:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
61+
[postData appendData:blobData];
62+
[postData appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
63+
}
64+
65+
}
66+
// close form data
67+
[postData appendData: [[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
68+
[request setHTTPBody:postData];
69+
// set content-length
70+
[mheaders setValue:[NSString stringWithFormat:@"%d",[postData length]] forKey:@"Content-Length"];
71+
[mheaders setValue:[NSString stringWithFormat:@"100-continue",[postData length]] forKey:@"Expect"];
72+
// appaned boundary to content-type
73+
[mheaders setValue:[NSString stringWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@", boundary] forKey:@"content-type"];
74+
75+
}
76+
77+
[request setHTTPMethod: method];
78+
[request setAllHTTPHeaderFields:mheaders];
79+
80+
// create thread for http request
81+
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
82+
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
83+
84+
NSHTTPURLResponse* resp = (NSHTTPURLResponse *) response;
85+
NSString* status = [NSString stringWithFormat:@"%d", resp.statusCode];
86+
87+
if(connectionError)
88+
{
89+
callback(@[[connectionError localizedDescription], [NSNull null]]);
90+
}
91+
else if(![status isEqualToString:@"200"]) {
92+
callback(@[status, [NSNull null]]);
93+
}
94+
else {
95+
callback(@[[NSNull null], [data base64EncodedStringWithOptions:0]]);
96+
}
97+
98+
}];
99+
100+
}
101+
18102
// Fetch blob data request
19103
RCT_EXPORT_METHOD(fetchBlob:(NSString *)method url:(NSString *)url headers:(NSDictionary *)headers body:(NSString *)body callback:(RCTResponseSenderBlock)callback)
20104
{
@@ -23,16 +107,26 @@ @implementation RNFetchBlob
23107
initWithURL:[NSURL
24108
URLWithString: url]];
25109

110+
NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] init];
111+
112+
// make headers case insensitive
113+
for(NSString * key in headers) {
114+
[mheaders setValue:[headers valueForKey:key] forKey:[key lowercaseString]];
115+
}
116+
26117
// if method is POST or PUT, convert data string format
27118
if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
119+
28120
NSData* blobData = [[NSData alloc] initWithBase64EncodedString:body options:0];
29121
NSMutableData* postBody = [[NSMutableData alloc] init];
30122
[postBody appendData:[NSData dataWithData:blobData]];
31123
[request setHTTPBody:postBody];
124+
[mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
125+
32126
}
33127

34128
[request setHTTPMethod: method];
35-
[request setAllHTTPHeaderFields:headers];
129+
[request setAllHTTPHeaderFields:mheaders];
36130

37131
// create thread for http request
38132
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
@@ -56,4 +150,5 @@ @implementation RNFetchBlob
56150

57151
}
58152

153+
59154
@end

0 commit comments

Comments
 (0)