Compare commits

...
Author SHA1 Message Date
Tobias Becht 4ef17d1af5 fix: handle 'missing' options 2023-02-09 11:48:37 +01:00
Tobias Becht 767f638635 feat: upload file without formdata 2023-02-08 17:25:57 +01:00
5 changed files with 143 additions and 45 deletions
@@ -163,12 +163,17 @@ public class CordovaHttpPlugin extends CordovaPlugin implements Observer {
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);
@@ -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);
+104 -39
View File
@@ -460,50 +460,30 @@
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) {
[weakSelf removeRequest:reqId];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
[[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
} failure:^(NSURLSessionTask *task, NSError *error) {
@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];
@@ -512,10 +492,95 @@
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
[[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
}];
[manager invalidateSessionCancelingTasks:YES];
};
void (^onSuccess)(NSURLSessionTask *, id) = ^(NSURLSessionTask *task, id responseObject) {
[weakSelf removeRequest:reqId];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
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];
}
+2 -2
View File
@@ -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),
@@ -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)
};
});
}
};
+7 -1
View File
@@ -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);