feat: upload file without formdata

This commit is contained in:
Tobias Becht
2023-02-08 17:25:57 +01:00
parent 6fc8a7e06d
commit 767f638635
4 changed files with 141 additions and 43 deletions
@@ -163,12 +163,17 @@ public class CordovaHttpPlugin extends CordovaPlugin implements Observer {
int readTimeout = args.getInt(5) * 1000; int readTimeout = args.getInt(5) * 1000;
boolean followRedirect = args.getBoolean(6); boolean followRedirect = args.getBoolean(6);
String responseType = args.getString(7); 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); CordovaObservableCallbackContext observableCallbackContext = new CordovaObservableCallbackContext(callbackContext, reqId);
CordovaHttpUpload upload = new CordovaHttpUpload(url, headers, filePaths, uploadNames, connectTimeout, readTimeout, followRedirect, 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); startRequest(reqId, observableCallbackContext, upload);
@@ -25,18 +25,40 @@ class CordovaHttpUpload extends CordovaHttpBase {
private JSONArray uploadNames; private JSONArray uploadNames;
private Context applicationContext; private Context applicationContext;
private boolean submitRaw = false;
public CordovaHttpUpload(String url, JSONObject headers, JSONArray filePaths, JSONArray uploadNames, int connectTimeout, int readTimeout, 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) { Context applicationContext, CordovaObservableCallbackContext callbackContext) {
super("POST", url, headers, connectTimeout, readTimeout, followRedirects, responseType, tlsConfiguration, callbackContext); super("POST", url, headers, connectTimeout, readTimeout, followRedirects, responseType, tlsConfiguration, callbackContext);
this.filePaths = filePaths; this.filePaths = filePaths;
this.uploadNames = uploadNames; this.uploadNames = uploadNames;
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
this.submitRaw = submitRaw;
} }
@Override @Override
protected void sendBody(HttpRequest request) throws Exception { 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) { for (int i = 0; i < this.filePaths.length(); ++i) {
String uploadName = this.uploadNames.getString(i); String uploadName = this.uploadNames.getString(i);
String filePath = this.filePaths.getString(i); String filePath = this.filePaths.getString(i);
+104 -39
View File
@@ -460,50 +460,30 @@
NSDictionary *headers = [command.arguments objectAtIndex:1]; NSDictionary *headers = [command.arguments objectAtIndex:1];
NSArray *filePaths = [command.arguments objectAtIndex: 2]; NSArray *filePaths = [command.arguments objectAtIndex: 2];
NSArray *names = [command.arguments objectAtIndex: 3]; 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]; NSTimeInterval readTimeout = [[command.arguments objectAtIndex:5] doubleValue];
bool followRedirect = [[command.arguments objectAtIndex:6] boolValue]; bool followRedirect = [[command.arguments objectAtIndex:6] boolValue];
NSString *responseType = [command.arguments objectAtIndex:7]; NSString *responseType = [command.arguments objectAtIndex:7];
NSNumber *reqId = [command.arguments objectAtIndex:8]; NSDictionary *transmitOptions = [command.arguments objectAtIndex:8];
NSNumber *reqId = [command.arguments objectAtIndex:9];
[self setRequestHeaders: headers forManager: manager];
[self setTimeout:readTimeout forManager:manager]; NSString *transmitFileType = [transmitOptions objectForKey:@"transmitFileAs"];
[self setRedirect:followRedirect forManager:manager];
[self setResponseSerializer:responseType forManager:manager];
CordovaHttpPlugin* __weak weakSelf = self; CordovaHttpPlugin* __weak weakSelf = self;
[[SDNetworkActivityIndicator sharedActivityIndicator] startActivity]; [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity];
@try { @try
NSURLSessionDataTask *task = [manager POST:url parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { {
NSError *error; NSURLSessionDataTask* task;
for (int i = 0; i < [filePaths count]; i++) {
NSString *filePath = (NSString *) [filePaths objectAtIndex:i]; void (^setupManager)(void) = ^() {
NSString *uploadName = (NSString *) [names objectAtIndex:i]; [self setRequestHeaders: headers forManager: manager];
NSURL *fileURL = [NSURL URLWithString: filePath]; [self setTimeout:readTimeout forManager:manager];
[formData appendPartWithFileURL:fileURL name:uploadName error:&error]; [self setRedirect:followRedirect forManager:manager];
} [self setResponseSerializer:responseType forManager:manager];
if (error) { };
[weakSelf removeRequest:reqId];
void (^onFailure)(NSURLSessionTask *, NSError *) = ^(NSURLSessionTask *task, NSError *error) {
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) {
[weakSelf removeRequest:reqId]; [weakSelf removeRequest:reqId];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
@@ -512,10 +492,95 @@
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
[weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
[[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; [[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]; [self addRequest:reqId forTask:task];
} }
@catch (NSException *exception) { @catch (NSException *exception)
{
[[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
[self handleException:exception withCommand:command]; [self handleException:exception withCommand:command];
} }
+7 -1
View File
@@ -180,7 +180,13 @@ module.exports = function init(exec, cookieHandler, urlUtil, helpers, globalConf
break; break;
case 'upload': case 'upload':
var fileOptions = helpers.checkUploadFileOptions(options.filePath, options.name); 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; break;
case 'download': case 'download':
var filePath = helpers.checkDownloadFilePath(options.filePath); var filePath = helpers.checkDownloadFilePath(options.filePath);