Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/android/com/silkimen/cordovahttp/CordovaHttpPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,17 @@ private boolean uploadFiles(final JSONArray args, final CallbackContext callback
int readTimeout = args.getInt(5) * 1000;
boolean followRedirect = args.getBoolean(6);
String responseType = args.getString(7);
Integer reqId = args.getInt(8);
JSONObject transmitOptions = args.getJSONObject(8);
Integer reqId = args.getInt(9);

// new file transmission options
String transmitFileType = transmitOptions.getString("transmitFileAs");
boolean submitRaw = transmitFileType.equalsIgnoreCase("BINARY");

CordovaObservableCallbackContext observableCallbackContext = new CordovaObservableCallbackContext(callbackContext, reqId);

CordovaHttpUpload upload = new CordovaHttpUpload(url, headers, filePaths, uploadNames, connectTimeout, readTimeout, followRedirect,
responseType, this.tlsConfiguration, this.cordova.getActivity().getApplicationContext(), observableCallbackContext);
responseType, this.tlsConfiguration, submitRaw, this.cordova.getActivity().getApplicationContext(), observableCallbackContext);

startRequest(reqId, observableCallbackContext, upload);

Expand Down
24 changes: 23 additions & 1 deletion src/android/com/silkimen/cordovahttp/CordovaHttpUpload.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,40 @@ class CordovaHttpUpload extends CordovaHttpBase {
private JSONArray uploadNames;
private Context applicationContext;

private boolean submitRaw = false;

public CordovaHttpUpload(String url, JSONObject headers, JSONArray filePaths, JSONArray uploadNames, int connectTimeout, int readTimeout,
boolean followRedirects, String responseType, TLSConfiguration tlsConfiguration,
boolean followRedirects, String responseType, TLSConfiguration tlsConfiguration, boolean submitRaw,
Context applicationContext, CordovaObservableCallbackContext callbackContext) {

super("POST", url, headers, connectTimeout, readTimeout, followRedirects, responseType, tlsConfiguration, callbackContext);
this.filePaths = filePaths;
this.uploadNames = uploadNames;
this.applicationContext = applicationContext;
this.submitRaw = submitRaw;
}

@Override
protected void sendBody(HttpRequest request) throws Exception {
if (this.submitRaw) {
if (this.filePaths.length() != 1) {
throw new IllegalArgumentException("Can only transmit a single file. Multiple files are not supported in this mode.");
}

String filePath = this.filePaths.getString(0);
Uri fileURI = Uri.parse(filePath);

if (ContentResolver.SCHEME_FILE.equals((fileURI.getScheme()))) {
File file = new File(new URI(filePath));
request.send(file);
} else if (ContentResolver.SCHEME_CONTENT.equals(fileURI.getScheme())) {
InputStream inputStream = this.applicationContext.getContentResolver().openInputStream(fileURI);
request.send(inputStream);
}

return;
}

for (int i = 0; i < this.filePaths.length(); ++i) {
String uploadName = this.uploadNames.getString(i);
String filePath = this.filePaths.getString(i);
Expand Down
135 changes: 100 additions & 35 deletions src/ios/CordovaHttpPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -460,62 +460,127 @@ - (void)uploadFiles:(CDVInvokedUrlCommand*)command {
NSDictionary *headers = [command.arguments objectAtIndex:1];
NSArray *filePaths = [command.arguments objectAtIndex: 2];
NSArray *names = [command.arguments objectAtIndex: 3];
NSTimeInterval connectTimeout = [[command.arguments objectAtIndex:4] doubleValue];
NSTimeInterval _connectTimeout = [[command.arguments objectAtIndex:4] doubleValue];
NSTimeInterval readTimeout = [[command.arguments objectAtIndex:5] doubleValue];
bool followRedirect = [[command.arguments objectAtIndex:6] boolValue];
NSString *responseType = [command.arguments objectAtIndex:7];
NSNumber *reqId = [command.arguments objectAtIndex:8];

[self setRequestHeaders: headers forManager: manager];
[self setTimeout:readTimeout forManager:manager];
[self setRedirect:followRedirect forManager:manager];
[self setResponseSerializer:responseType forManager:manager];
NSDictionary *transmitOptions = [command.arguments objectAtIndex:8];
NSNumber *reqId = [command.arguments objectAtIndex:9];

NSString *transmitFileType = [transmitOptions objectForKey:@"transmitFileAs"];

CordovaHttpPlugin* __weak weakSelf = self;
[[SDNetworkActivityIndicator sharedActivityIndicator] startActivity];

@try {
NSURLSessionDataTask *task = [manager POST:url parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
NSError *error;
for (int i = 0; i < [filePaths count]; i++) {
NSString *filePath = (NSString *) [filePaths objectAtIndex:i];
NSString *uploadName = (NSString *) [names objectAtIndex:i];
NSURL *fileURL = [NSURL URLWithString: filePath];
[formData appendPartWithFileURL:fileURL name:uploadName error:&error];
}
if (error) {
[weakSelf removeRequest:reqId];

NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setObject:[NSNumber numberWithInt:500] forKey:@"status"];
[dictionary setObject:@"Could not add file to post body." forKey:@"error"];
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
[[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
return;
}
} progress:nil success:^(NSURLSessionTask *task, id responseObject) {
@try
{
NSURLSessionDataTask* task;

void (^setupManager)(void) = ^() {
[self setRequestHeaders: headers forManager: manager];
[self setTimeout:readTimeout forManager:manager];
[self setRedirect:followRedirect forManager:manager];
[self setResponseSerializer:responseType forManager:manager];
};

void (^onFailure)(NSURLSessionTask *, NSError *) = ^(NSURLSessionTask *task, NSError *error) {
[weakSelf removeRequest:reqId];

NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];

CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
[[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
} failure:^(NSURLSessionTask *task, NSError *error) {
[manager invalidateSessionCancelingTasks:YES];
};

void (^onSuccess)(NSURLSessionTask *, id) = ^(NSURLSessionTask *task, id responseObject) {
[weakSelf removeRequest:reqId];

NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];

CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
[[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
}];
[manager invalidateSessionCancelingTasks:YES];
};

bool submitRaw = [transmitFileType isEqualToString:@"BINARY"];

// RAW
if (submitRaw)
{
if ([filePaths count] == 1)
{
// setup the request serializer to submit the raw file content
manager.requestSerializer = [BinaryRequestSerializer serializer];
setupManager();

NSURL *fileURL = [NSURL URLWithString:[filePaths objectAtIndex:0]];
NSError *error;
NSData *fileData = [NSData dataWithContentsOfURL:fileURL options:0 error:&error];

if (error)
{
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[self handleError:dictionary withResponse:nil error:error];
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
[[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
[manager invalidateSessionCancelingTasks:YES];
return;
}

task = [manager uploadTaskWithHTTPMethod:@"POST" URLString:url parameters:fileData progress:nil success:onSuccess failure:onFailure];
}
else
{
[NSException raise:@"ArgumentException" format:@"Can only transmit a single file. Multiple files are not supported in this mode."];
}
}
else // FALLBACK: Multipart / FormData
{
setupManager();
task = [manager
POST:url
parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
NSError *error;

for (int i = 0; i < [filePaths count]; i++)
{
NSString *filePath = (NSString *) [filePaths objectAtIndex:i];
NSString *uploadName = (NSString *) [names objectAtIndex:i];
NSURL *fileURL = [NSURL URLWithString: filePath];
[formData appendPartWithFileURL:fileURL name:uploadName error:&error];
}

if (error)
{
[weakSelf removeRequest:reqId];

NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setObject:[NSNumber numberWithInt:500] forKey:@"status"];
[dictionary setObject:@"Could not add file to post body." forKey:@"error"];
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
[[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
return;
}
}
progress:nil
success:onSuccess
failure:onFailure
];
}

[self addRequest:reqId forTask:task];
}
@catch (NSException *exception) {
@catch (NSException *exception)
{
[[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
[self handleException:exception withCommand:command];
}
Expand Down
4 changes: 2 additions & 2 deletions www/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ module.exports = function init(global, jsUtil, cookieHandler, messages, base64,
function handleMissingOptions(options, globals) {
options = options || {};

return {
return Object.assign({}, options, {
data: jsUtil.getTypeOf(options.data) === 'Undefined' ? null : options.data,
filePath: options.filePath,
followRedirect: checkFollowRedirectValue(options.followRedirect || globals.followRedirect),
Expand All @@ -511,6 +511,6 @@ module.exports = function init(global, jsUtil, cookieHandler, messages, base64,
connectTimeout: checkTimeoutValue(options.connectTimeout || globals.connectTimeout),
readTimeout: checkTimeoutValue(options.readTimeout || globals.readTimeout),
timeout: checkTimeoutValue(options.timeout || globals.timeout)
};
});
}
};
8 changes: 7 additions & 1 deletion www/public-interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,13 @@ module.exports = function init(exec, cookieHandler, urlUtil, helpers, globalConf
break;
case 'upload':
var fileOptions = helpers.checkUploadFileOptions(options.filePath, options.name);
exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFiles', [url, headers, fileOptions.filePaths, fileOptions.names, options.connectTimeout, options.readTimeout, options.followRedirect, options.responseType, reqId]);

// support uploading files as octet-stream / encoded string instead of form-data
var transmitOptions = {};
transmitOptions.transmitFileAs = options.transmitFileAs || 'FORMDATA';
// transmitOptions.transmitMethod = options.transmitMethod || 'POST';

exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFiles', [url, headers, fileOptions.filePaths, fileOptions.names, options.connectTimeout, options.readTimeout, options.followRedirect, options.responseType, transmitOptions, reqId]);
break;
case 'download':
var filePath = helpers.checkDownloadFilePath(options.filePath);
Expand Down