diff --git a/README.md b/README.md index b09d1383..97c64e02 100644 --- a/README.md +++ b/README.md @@ -410,6 +410,8 @@ cordova.plugin.http.uploadFile("https://google.com/", { console.log(response.status); }, function(response) { console.error(response.error); +}, function(progressData) { + console.log((progressData.transferred / progressData.total * 100) + ' percent complete') }); ``` diff --git a/src/android/com/silkimen/cordovahttp/CordovaHttpPlugin.java b/src/android/com/silkimen/cordovahttp/CordovaHttpPlugin.java index 9a7d34ad..cf3fc2c7 100644 --- a/src/android/com/silkimen/cordovahttp/CordovaHttpPlugin.java +++ b/src/android/com/silkimen/cordovahttp/CordovaHttpPlugin.java @@ -164,11 +164,12 @@ private boolean uploadFiles(final JSONArray args, final CallbackContext callback boolean followRedirect = args.getBoolean(6); String responseType = args.getString(7); Integer reqId = args.getInt(8); + boolean hasProgressCallback = args.getBoolean(9); 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); + hasProgressCallback, responseType, this.tlsConfiguration, this.cordova.getActivity().getApplicationContext(), observableCallbackContext); startRequest(reqId, observableCallbackContext, upload); diff --git a/src/android/com/silkimen/cordovahttp/CordovaHttpUpload.java b/src/android/com/silkimen/cordovahttp/CordovaHttpUpload.java index d37464d2..ebceace8 100644 --- a/src/android/com/silkimen/cordovahttp/CordovaHttpUpload.java +++ b/src/android/com/silkimen/cordovahttp/CordovaHttpUpload.java @@ -5,6 +5,7 @@ import android.database.Cursor; import android.net.Uri; import android.provider.OpenableColumns; +import android.util.Log; import android.webkit.MimeTypeMap; import com.silkimen.http.HttpRequest; @@ -17,22 +18,26 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLSocketFactory; +import org.apache.cordova.PluginResult; import org.json.JSONArray; +import org.json.JSONException; import org.json.JSONObject; class CordovaHttpUpload extends CordovaHttpBase { private JSONArray filePaths; private JSONArray uploadNames; private Context applicationContext; + private boolean hasProgressHandler; public CordovaHttpUpload(String url, JSONObject headers, JSONArray filePaths, JSONArray uploadNames, int connectTimeout, int readTimeout, - boolean followRedirects, String responseType, TLSConfiguration tlsConfiguration, + boolean followRedirects, boolean hasProgressHandler, String responseType, TLSConfiguration tlsConfiguration, Context applicationContext, CordovaObservableCallbackContext callbackContext) { super("POST", url, headers, connectTimeout, readTimeout, followRedirects, responseType, tlsConfiguration, callbackContext); this.filePaths = filePaths; this.uploadNames = uploadNames; this.applicationContext = applicationContext; + this.hasProgressHandler = hasProgressHandler; } @Override @@ -60,6 +65,25 @@ protected void sendBody(HttpRequest request) throws Exception { request.part(uploadName, fileName, mimeType, inputStream); } + + if (hasProgressHandler) { + request.progress(new HttpRequest.UploadProgress() { + public void onUpload(long transferred, long total) { + JSONObject json = new JSONObject(); + try { + json.put("isProgress", true); + json.put("transferred", transferred); + json.put("total", total); + + PluginResult result = new PluginResult(PluginResult.Status.OK, json); + result.setKeepCallback(true); + callbackContext.getCallbackContext().sendPluginResult(result); + } catch (JSONException e) { + Log.e(TAG, "onUpload progress error", e); + } + } + }); + } } } diff --git a/src/ios/CordovaHttpPlugin.m b/src/ios/CordovaHttpPlugin.m index 97c98e01..645b1110 100644 --- a/src/ios/CordovaHttpPlugin.m +++ b/src/ios/CordovaHttpPlugin.m @@ -494,13 +494,22 @@ - (void)uploadFiles:(CDVInvokedUrlCommand*)command { [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; return; } - } progress:nil success:^(NSURLSessionTask *task, id responseObject) { + } progress:^(NSProgress *progress) { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + [dictionary setValue:[NSNumber numberWithBool:YES] forKey:@"isProgress"]; + [dictionary setValue:[NSNumber numberWithLongLong:progress.completedUnitCount] forKey:@"transferred"]; + [dictionary setValue:[NSNumber numberWithLongLong:progress.totalUnitCount] forKey:@"total"]; + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary]; + [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]]; + [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + } 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]; + [pluginResult setKeepCallback:[NSNumber numberWithBool:NO]]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; } failure:^(NSURLSessionTask *task, NSError *error) { @@ -510,6 +519,7 @@ - (void)uploadFiles:(CDVInvokedUrlCommand*)command { [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; + [pluginResult setKeepCallback:[NSNumber numberWithBool:NO]]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; }]; diff --git a/www/helpers.js b/www/helpers.js index ed070fe6..a2dd3b6c 100644 --- a/www/helpers.js +++ b/www/helpers.js @@ -510,7 +510,8 @@ module.exports = function init(global, jsUtil, cookieHandler, messages, base64, serializer: checkSerializer(options.serializer || globals.serializer), connectTimeout: checkTimeoutValue(options.connectTimeout || globals.connectTimeout), readTimeout: checkTimeoutValue(options.readTimeout || globals.readTimeout), - timeout: checkTimeoutValue(options.timeout || globals.timeout) + timeout: checkTimeoutValue(options.timeout || globals.timeout), + onProgress: options.onProgress }; } }; diff --git a/www/public-interface.js b/www/public-interface.js index 66b52612..88af3e2e 100644 --- a/www/public-interface.js +++ b/www/public-interface.js @@ -180,7 +180,14 @@ 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]); + var hasProgressCallback = options.onProgress != null; + exec(function(resp) { + if (resp != null && resp.isProgress) { + options.onProgress(resp); + } else { + onSuccess(resp); + } + }, onFail, 'CordovaHttpPlugin', 'uploadFiles', [url, headers, fileOptions.filePaths, fileOptions.names, options.connectTimeout, options.readTimeout, options.followRedirect, options.responseType, reqId, hasProgressCallback]); break; case 'download': var filePath = helpers.checkDownloadFilePath(options.filePath); @@ -223,8 +230,8 @@ module.exports = function init(exec, cookieHandler, urlUtil, helpers, globalConf return publicInterface.sendRequest(url, { method: 'options', params: params, headers: headers }, success, failure); }; - function uploadFile(url, params, headers, filePath, name, success, failure) { - return publicInterface.sendRequest(url, { method: 'upload', params: params, headers: headers, filePath: filePath, name: name }, success, failure); + function uploadFile(url, params, headers, filePath, name, success, failure, progress) { + return publicInterface.sendRequest(url, { method: 'upload', params: params, headers: headers, filePath: filePath, name: name, onProgress: progress }, success, failure); } function downloadFile(url, params, headers, filePath, success, failure) {