Merge branch 'CB-6503'
diff --git a/README.md b/README.md
index 7605ce3..4ee0774 100644
--- a/README.md
+++ b/README.md
@@ -57,7 +57,7 @@
# FileTransfer
The `FileTransfer` object provides a way to upload files using an HTTP
-multi-part POST request, and to download files as well.
+multi-part POST or PUT request, and to download files as well.
## Properties
@@ -91,8 +91,9 @@
- __mimeType__: The mime type of the data to upload. Defaults to `image/jpeg`. (DOMString)
- __params__: A set of optional key/value pairs to pass in the HTTP request. (Object)
- __chunkedMode__: Whether to upload the data in chunked streaming mode. Defaults to `true`. (Boolean)
- - __headers__: A map of header name/header values. Use an array to specify more than one value. (Object)
-
+ - __headers__: A map of header name/header values. Use an array to specify more than one value. On iOS, FireOS, and Android, if a header named Content-Type is present, multipart form data will NOT be used. (Object)
+ - __httpMethod__: The HTTP method to use e.g. POST or PUT. Defaults to `POST`. (DOMString)
+
- __trustAllHosts__: Optional parameter, defaults to `false`. If set to `true`, it accepts all security certificates. This is useful since Android rejects self-signed security certificates. Not recommended for production use. Supported on Android and iOS. _(boolean)_
### Example
diff --git a/src/amazon/FileTransfer.java b/src/amazon/FileTransfer.java
index 513400e..1563a39 100644
--- a/src/amazon/FileTransfer.java
+++ b/src/amazon/FileTransfer.java
@@ -315,8 +315,12 @@
// Use a post method.
conn.setRequestMethod(httpMethod);
- conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
+ // if we specified a Content-Type header, don't do multipart form upload
+ boolean multipartFormUpload = (headers == null) || !headers.has("Content-Type");
+ if (multipartFormUpload) {
+ conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
+ }
// Set the cookies on the response
String cookie = AmazonCookieManager.getInstance().getCookie(target);
if (cookie != null) {
@@ -362,7 +366,9 @@
int stringLength = beforeDataBytes.length + tailParamsBytes.length;
if (readResult.length >= 0) {
- fixedLength = (int)readResult.length + stringLength;
+ fixedLength = (int)readResult.length;
+ if (multipartFormUpload)
+ fixedLength += stringLength;
progress.setLengthComputable(true);
progress.setTotal(fixedLength);
}
@@ -393,10 +399,12 @@
}
context.currentOutputStream = sendStream;
}
- //We don't want to change encoding, we just want this to write for all Unicode.
- sendStream.write(beforeDataBytes);
- totalBytes += beforeDataBytes.length;
-
+
+ if (multipartFormUpload) {
+ //We don't want to change encoding, we just want this to write for all Unicode.
+ sendStream.write(beforeDataBytes);
+ totalBytes += beforeDataBytes.length;
+ }
// create a buffer of maximum size
int bytesAvailable = readResult.inputStream.available();
int bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
@@ -425,9 +433,11 @@
context.sendPluginResult(progressResult);
}
- // send multipart form data necessary after file data...
- sendStream.write(tailParamsBytes);
- totalBytes += tailParamsBytes.length;
+ if (multipartFormUpload) {
+ // send multipart form data necessary after file data...
+ sendStream.write(tailParamsBytes);
+ totalBytes += tailParamsBytes.length;
+ }
sendStream.flush();
} finally {
safeClose(readResult.inputStream);
diff --git a/src/android/FileTransfer.java b/src/android/FileTransfer.java
index 882bf3f..9c8dacb 100644
--- a/src/android/FileTransfer.java
+++ b/src/android/FileTransfer.java
@@ -341,8 +341,13 @@
// Use a post method.
conn.setRequestMethod(httpMethod);
- conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
-
+
+ // if we specified a Content-Type header, don't do multipart form upload
+ boolean multipartFormUpload = (headers == null) || !headers.has("Content-Type");
+ if (multipartFormUpload) {
+ conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
+ }
+
// Set the cookies on the response
String cookie = getCookies(target);
@@ -389,7 +394,9 @@
int stringLength = beforeDataBytes.length + tailParamsBytes.length;
if (readResult.length >= 0) {
- fixedLength = (int)readResult.length + stringLength;
+ fixedLength = (int)readResult.length;
+ if (multipartFormUpload)
+ fixedLength += stringLength;
progress.setLengthComputable(true);
progress.setTotal(fixedLength);
}
@@ -420,10 +427,13 @@
}
context.connection = conn;
}
- //We don't want to change encoding, we just want this to write for all Unicode.
- sendStream.write(beforeDataBytes);
- totalBytes += beforeDataBytes.length;
-
+
+ if (multipartFormUpload) {
+ //We don't want to change encoding, we just want this to write for all Unicode.
+ sendStream.write(beforeDataBytes);
+ totalBytes += beforeDataBytes.length;
+ }
+
// create a buffer of maximum size
int bytesAvailable = readResult.inputStream.available();
int bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
@@ -452,9 +462,11 @@
context.sendPluginResult(progressResult);
}
- // send multipart form data necessary after file data...
- sendStream.write(tailParamsBytes);
- totalBytes += tailParamsBytes.length;
+ if (multipartFormUpload) {
+ // send multipart form data necessary after file data...
+ sendStream.write(tailParamsBytes);
+ totalBytes += tailParamsBytes.length;
+ }
sendStream.flush();
} finally {
safeClose(readResult.inputStream);
diff --git a/src/ios/CDVFileTransfer.m b/src/ios/CDVFileTransfer.m
index 3031159..70ddb35 100644
--- a/src/ios/CDVFileTransfer.m
+++ b/src/ios/CDVFileTransfer.m
@@ -183,8 +183,12 @@
[req setHTTPShouldHandleCookies:NO];
}
- NSString* contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", kFormBoundary];
- [req setValue:contentType forHTTPHeaderField:@"Content-Type"];
+ // if we specified a Content-Type header, don't do multipart form upload
+ BOOL multipartFormUpload = [headers objectForKey:@"Content-Type"] == nil;
+ if (multipartFormUpload) {
+ NSString* contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", kFormBoundary];
+ [req setValue:contentType forHTTPHeaderField:@"Content-Type"];
+ }
[self applyRequestHeaders:headers toRequest:req];
NSData* formBoundaryData = [[NSString stringWithFormat:@"--%@\r\n", kFormBoundary] dataUsingEncoding:NSUTF8StringEncoding];
@@ -220,7 +224,11 @@
DLog(@"fileData length: %d", [fileData length]);
NSData* postBodyAfterFile = [[NSString stringWithFormat:@"\r\n--%@--\r\n", kFormBoundary] dataUsingEncoding:NSUTF8StringEncoding];
- long long totalPayloadLength = [postBodyBeforeFile length] + [fileData length] + [postBodyAfterFile length];
+ long long totalPayloadLength = [fileData length];
+ if (multipartFormUpload) {
+ totalPayloadLength += [postBodyBeforeFile length] + [postBodyAfterFile length];
+ }
+
[req setValue:[[NSNumber numberWithLongLong:totalPayloadLength] stringValue] forHTTPHeaderField:@"Content-Length"];
if (chunkedMode) {
@@ -231,14 +239,18 @@
[self.commandDelegate runInBackground:^{
if (CFWriteStreamOpen(writeStream)) {
- NSData* chunks[] = {postBodyBeforeFile, fileData, postBodyAfterFile};
- int numChunks = sizeof(chunks) / sizeof(chunks[0]);
+ if (multipartFormUpload) {
+ NSData* chunks[] = { postBodyBeforeFile, fileData, postBodyAfterFile };
+ int numChunks = sizeof(chunks) / sizeof(chunks[0]);
- for (int i = 0; i < numChunks; ++i) {
- CFIndex result = WriteDataToStream(chunks[i], writeStream);
- if (result <= 0) {
- break;
+ for (int i = 0; i < numChunks; ++i) {
+ CFIndex result = WriteDataToStream(chunks[i], writeStream);
+ if (result <= 0) {
+ break;
+ }
}
+ } else {
+ WriteDataToStream(fileData, writeStream);
}
} else {
NSLog(@"FileTransfer: Failed to open writeStream");
@@ -247,9 +259,13 @@
CFRelease(writeStream);
}];
} else {
- [postBodyBeforeFile appendData:fileData];
- [postBodyBeforeFile appendData:postBodyAfterFile];
- [req setHTTPBody:postBodyBeforeFile];
+ if (multipartFormUpload) {
+ [postBodyBeforeFile appendData:fileData];
+ [postBodyBeforeFile appendData:postBodyAfterFile];
+ [req setHTTPBody:postBodyBeforeFile];
+ } else {
+ [req setHTTPBody:fileData];
+ }
}
return req;
}