From 6f91ac3a3068a12b7bffe3d03471943a1690941e Mon Sep 17 00:00:00 2001 From: Bas Bosman Date: Sun, 26 Jan 2014 22:40:23 +0100 Subject: [PATCH 01/17] CB-4907 Close stream when we're finished with it --- src/android/FileTransfer.java | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/android/FileTransfer.java b/src/android/FileTransfer.java index 079cd91..6ad30dd 100644 --- a/src/android/FileTransfer.java +++ b/src/android/FileTransfer.java @@ -582,15 +582,19 @@ public class FileTransfer extends CordovaPlugin { if(err != null) { BufferedReader reader = new BufferedReader(new InputStreamReader(err, "UTF-8")); - String line = reader.readLine(); - while(line != null) - { - bodyBuilder.append(line); - line = reader.readLine(); - if(line != null) - bodyBuilder.append('\n'); + try { + String line = reader.readLine(); + while(line != null) { + bodyBuilder.append(line); + line = reader.readLine(); + if(line != null) { + bodyBuilder.append('\n'); + } + } + body = bodyBuilder.toString(); + } finally { + reader.close(); } - body = bodyBuilder.toString(); } } // IOException can leave connection object in a bad state, so catch all exceptions. From 651460fb6b41035c96bcc31a38621ec8100648f1 Mon Sep 17 00:00:00 2001 From: Christoph Neumann Date: Thu, 26 Sep 2013 09:35:11 -0500 Subject: [PATCH 02/17] CB-6000 Nginx rejects Content-Type without a space before "boundary". From: https://github.com/apache/cordova-plugin-file-transfer/pull/6 --- src/android/FileTransfer.java | 2 +- src/wp/FileTransfer.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/android/FileTransfer.java b/src/android/FileTransfer.java index 6ad30dd..7ea23ca 100644 --- a/src/android/FileTransfer.java +++ b/src/android/FileTransfer.java @@ -315,7 +315,7 @@ public class FileTransfer extends CordovaPlugin { // Use a post method. conn.setRequestMethod(httpMethod); - conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY); + conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); // Set the cookies on the response String cookie = CookieManager.getInstance().getCookie(target); diff --git a/src/wp/FileTransfer.cs b/src/wp/FileTransfer.cs index f9fe3fe..f8b6ed5 100644 --- a/src/wp/FileTransfer.cs +++ b/src/wp/FileTransfer.cs @@ -285,7 +285,7 @@ namespace WPCordovaClassLib.Cordova.Commands return; } webRequest = (HttpWebRequest)WebRequest.Create(serverUri); - webRequest.ContentType = "multipart/form-data;boundary=" + Boundary; + webRequest.ContentType = "multipart/form-data; boundary=" + Boundary; webRequest.Method = uploadOptions.Method; if (!string.IsNullOrEmpty(uploadOptions.Headers)) From 28fb0a7c4d07278d2f765f6762fb8b1a6fd1d2e4 Mon Sep 17 00:00:00 2001 From: Daniel Heffernan Date: Mon, 10 Feb 2014 14:58:37 -0500 Subject: [PATCH 03/17] CB-5588 iOS: Add response headers to upload result This change adds the HTTP response headers to the result for successful uploads. --- src/ios/CDVFileTransfer.h | 1 + src/ios/CDVFileTransfer.m | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ios/CDVFileTransfer.h b/src/ios/CDVFileTransfer.h index aa1cf9e..1ce7abe 100644 --- a/src/ios/CDVFileTransfer.h +++ b/src/ios/CDVFileTransfer.h @@ -64,6 +64,7 @@ extern NSString* const kOptionsKeyCookie; - (void)cancelTransfer:(NSURLConnection*)connection; @property (strong) NSMutableData* responseData; // atomic +@property (nonatomic, strong) NSDictionary* responseHeaders; @property (nonatomic, strong) CDVFileTransfer* command; @property (nonatomic, assign) CDVFileTransferDirection direction; @property (nonatomic, strong) NSURLConnection* connection; diff --git a/src/ios/CDVFileTransfer.m b/src/ios/CDVFileTransfer.m index 1ae0730..e35e2fe 100644 --- a/src/ios/CDVFileTransfer.m +++ b/src/ios/CDVFileTransfer.m @@ -513,7 +513,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) @implementation CDVFileTransferDelegate -@synthesize callbackId, connection = _connection, source, target, responseData, command, bytesTransfered, bytesExpected, direction, responseCode, objectId, targetFileHandle; +@synthesize callbackId, connection = _connection, source, target, responseData, responseHeaders, command, bytesTransfered, bytesExpected, direction, responseCode, objectId, targetFileHandle; - (void)connectionDidFinishLoading:(NSURLConnection*)connection { @@ -532,6 +532,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) uploadResult = [NSMutableDictionary dictionaryWithCapacity:3]; if (uploadResponse != nil) { [uploadResult setObject:uploadResponse forKey:@"response"]; + [uploadResult setObject:self.responseHeaders forKey:@"headers"]; } [uploadResult setObject:[NSNumber numberWithLongLong:self.bytesTransfered] forKey:@"bytesSent"]; [uploadResult setObject:[NSNumber numberWithInt:self.responseCode] forKey:@"responseCode"]; @@ -600,6 +601,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) self.responseCode = [httpResponse statusCode]; self.bytesExpected = [response expectedContentLength]; + self.responseHeaders = [httpResponse allHeaderFields]; if ((self.direction == CDV_TRANSFER_DOWNLOAD) && (self.responseCode == 200) && (self.bytesExpected == NSURLResponseUnknownLength)) { // Kick off HEAD request to server to get real length // bytesExpected will be updated when that response is returned From f8884981e4f2163650253e763170d38250d1ebfc Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Mon, 10 Feb 2014 15:11:05 -0500 Subject: [PATCH 04/17] CB-5588 Docs for upload headers. --- doc/index.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/index.md b/doc/index.md index 2c53c0a..76a5f52 100644 --- a/doc/index.md +++ b/doc/index.md @@ -154,6 +154,9 @@ A `FileUploadResult` object is passed to the success callback of the - __response__: The HTTP response returned by the server. (DOMString) +- __headers__: The HTTP response headers by the server. (Object) + - Currently supported on iOS only. + ### iOS Quirks - Does not support `responseCode` or `bytesSent`. From 3c242d8ba816aec8417723c31e08b23445d54eda Mon Sep 17 00:00:00 2001 From: Steven Gill Date: Wed, 5 Feb 2014 17:53:59 -0800 Subject: [PATCH 05/17] CB-5980 Updated version and RELEASENOTES.md for release 0.4.1 --- RELEASENOTES.md | 13 +++++++++++++ plugin.xml | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2ef1bfd..537f114 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -44,3 +44,16 @@ * CB-5466: Minor version bump * CB-5466: Update FileTransfer plugin to accept filesystem urls * Added amazon-fireos platform. Change to use amazon-fireos as the platform if the user agen string contains 'cordova-amazon-fireos' + +### 0.4.1 (Feb 05, 2014) +* CB-5365 Remove unused exception var to prevent warnings? +* CB-2421 explicitly write the bytesSent,responseCode,result to the FileUploadResult pending release of cordova-plugin-file dependency, added some sanity checks for callbacks +* iOS: Update for new file plugin api +* CB-5631 Removed SimpleTrackingInputStream.read(byte[] buffer) +* CB-5762 android: Fix lengthComputable set wrong for gzip downloads +* CB-4899 [BlackBerry10] Improve binary file transfer download +* Delete stale test/ directory +* CB-5722 [BlackBerry10] Update upload function to use native file object +* CB-5658 Delete stale snapshot of plugin docs +* Remove @1 designation from file plugin dependency until pushed to npm +* CB-5466: Update to work with filesystem URLs diff --git a/plugin.xml b/plugin.xml index b003925..4b039fb 100644 --- a/plugin.xml +++ b/plugin.xml @@ -2,7 +2,7 @@ + version="0.4.1"> File Transfer Cordova File Transfer Plugin Apache 2.0 From 914946857f6c4260b4f91e921cf51f0a68a32ea0 Mon Sep 17 00:00:00 2001 From: Steven Gill Date: Wed, 5 Feb 2014 18:13:30 -0800 Subject: [PATCH 06/17] CB-5980 Incremented plugin version on dev branch. --- plugin.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin.xml b/plugin.xml index 4b039fb..a1a9ebd 100644 --- a/plugin.xml +++ b/plugin.xml @@ -2,7 +2,7 @@ + version="0.4.2-dev"> File Transfer Cordova File Transfer Plugin Apache 2.0 From 31ac00d3ae35f9ca280cf4e6c9edc9df23ea95b5 Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Thu, 13 Feb 2014 09:49:09 -0500 Subject: [PATCH 07/17] CB-6022: Add backwards-compatibility notes to doc Also change "URI" and "path" references to "URL" where appropriate for consistency. --- doc/index.md | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/doc/index.md b/doc/index.md index 76a5f52..eb4db58 100644 --- a/doc/index.md +++ b/doc/index.md @@ -58,7 +58,7 @@ multi-part POST request, and to download files as well. __Parameters__: -- __filePath__: Full path of the file on the device. +- __fileURL__: Filesystem URL representing the file on the device. For backwards compatibility, this can also be the full path of the file on the device. (See [Backwards Compatibility Notes] below) - __server__: URL of the server to receive the file, as encoded by `encodeURI()`. @@ -78,7 +78,8 @@ __Parameters__: ### Example - // !! Assumes variable fileURI contains a valid URI to a text file on the device + // !! Assumes variable fileURL contains a valid URL to a text file on the device, + // for example, cdvfile://localhost/persistent/path/to/file.txt var win = function (r) { console.log("Code = " + r.responseCode); @@ -94,7 +95,7 @@ __Parameters__: var options = new FileUploadOptions(); options.fileKey = "file"; - options.fileName = fileURI.substr(fileURI.lastIndexOf('/') + 1); + options.fileName = fileURL.substr(fileURL.lastIndexOf('/') + 1); options.mimeType = "text/plain"; var params = {}; @@ -104,7 +105,7 @@ __Parameters__: options.params = params; var ft = new FileTransfer(); - ft.upload(fileURI, encodeURI("http://some.server.com/upload.php"), win, fail, options); + ft.upload(fileURL, encodeURI("http://some.server.com/upload.php"), win, fail, options); ### Example with Upload Headers and Progress Events (Android and iOS only) @@ -124,7 +125,7 @@ __Parameters__: var options = new FileUploadOptions(); options.fileKey="file"; - options.fileName=fileURI.substr(fileURI.lastIndexOf('/')+1); + options.fileName=fileURL.substr(fileURL.lastIndexOf('/')+1); options.mimeType="text/plain"; var headers={'headerParam':'headerValue'}; @@ -139,7 +140,7 @@ __Parameters__: loadingStatus.increment(); } }; - ft.upload(fileURI, uri, win, fail, options); + ft.upload(fileURL, uri, win, fail, options); ## FileUploadResult @@ -168,7 +169,7 @@ __Parameters__: - __source__: URL of the server to download the file, as encoded by `encodeURI()`. -- __target__: Full path of the file on the device. +- __target__: Filesystem url representing the file on the device. For backwards compatibility, this can also be the full path of the file on the device. (See [Backwards Compatibility Notes] below) - __successCallback__: A callback that is passed a `FileEntry` object. _(Function)_ @@ -180,14 +181,15 @@ __Parameters__: ### Example - // !! Assumes filePath is a valid path on the device + // !! Assumes variable fileURL contains a valid URL to a path on the device, + // for example, cdvfile://localhost/persistent/path/to/downloads/ var fileTransfer = new FileTransfer(); var uri = encodeURI("http://some.server.com/download.php"); fileTransfer.download( uri, - filePath, + fileURL, function(entry) { console.log("download complete: " + entry.fullPath); }, @@ -210,7 +212,8 @@ Aborts an in-progress transfer. The onerror callback is passed a FileTransferErr ### Example - // !! Assumes variable fileURI contains a valid URI to a text file on the device + // !! Assumes variable fileURL contains a valid URL to a text file on the device, + // for example, cdvfile://localhost/persistent/path/to/file.txt var win = function(r) { console.log("Should not be called."); @@ -229,7 +232,7 @@ Aborts an in-progress transfer. The onerror callback is passed a FileTransferErr options.mimeType="image/jpeg"; var ft = new FileTransfer(); - ft.upload(fileURI, encodeURI("http://some.server.com/upload.php"), win, fail, options); + ft.upload(fileURL, encodeURI("http://some.server.com/upload.php"), win, fail, options); ft.abort(); @@ -241,9 +244,9 @@ A `FileTransferError` object is passed to an error callback when an error occurs - __code__: One of the predefined error codes listed below. (Number) -- __source__: URI to the source. (String) +- __source__: URL to the source. (String) -- __target__: URI to the target. (String) +- __target__: URL to the target. (String) - __http_status__: HTTP status code. This attribute is only available when a response code is received from the HTTP connection. (Number) @@ -254,3 +257,21 @@ A `FileTransferError` object is passed to an error callback when an error occurs - `FileTransferError.CONNECTION_ERR` - `FileTransferError.ABORT_ERR` +## Backwards Compatibility Notes + +Previous versions of this plugin would only accept device-absolute-file-paths as the source for uploads, or as the target for downloads. These paths would typically be of the form + + /var/mobile/Applications//Documents/path/to/file (iOS) + /storage/emulated/0/path/to/file (Android) + +For backwards compatibility, these paths are still accepted, and if your application has recorded paths like these in persistent storage, then they can continue to be used. + +These paths were previously exposed in the `fullPath` property of `FileEntry` and `DirectoryEntry` objects returned by the File plugin. New versions of the File plugin, however, no longer expose these paths to JavaScript. + +If you are upgrading to a new (1.0.0 or newer) version of File, and you have previously been using `entry.fullPath` as arguments to `download()` or `upload()`, then you will need to change your code to use filesystem URLs instead. + +`FileEntry.toURL()` and `DirectoryEntry.toURL()` return a filesystem URL of the form + + cdvfile://localhost/persistent/path/to/file + +which can be used in place of the absolute file path in both `download()` and `upload()` methods. From 35f80e42ec0a0343022bffa88b1cbd2e68f0fc3f Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Tue, 18 Feb 2014 15:25:01 -0500 Subject: [PATCH 08/17] CB-6050: Use instance method on actual file plugin object to get FileEntry to return on download --- plugin.xml | 2 +- src/android/FileTransfer.java | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/plugin.xml b/plugin.xml index a1a9ebd..d93cdac 100644 --- a/plugin.xml +++ b/plugin.xml @@ -11,7 +11,7 @@ https://issues.apache.org/jira/browse/CB/component/12320650 - + diff --git a/src/android/FileTransfer.java b/src/android/FileTransfer.java index 7ea23ca..e370c5f 100644 --- a/src/android/FileTransfer.java +++ b/src/android/FileTransfer.java @@ -797,9 +797,21 @@ public class FileTransfer extends CordovaPlugin { Log.d(LOG_TAG, "Saved file: " + target); // create FileEntry object - JSONObject fileEntry = FileUtils.getEntry(file); + FileUtils filePlugin = (FileUtils)webView.pluginManager.getPlugin("File"); + if (filePlugin != null) { + JSONObject fileEntry = filePlugin.getEntryForFile(file); + if (fileEntry != null) { + result = new PluginResult(PluginResult.Status.OK, fileEntry); + } else { + JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, connection); + Log.e(LOG_TAG, "File plugin cannot represent download path"); + result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error); + } + } else { + Log.e(LOG_TAG, "File plugin not found; cannot save downloaded file"); + result = new PluginResult(PluginResult.Status.ERROR, "File plugin not found; cannot save downloaded file"); + } - result = new PluginResult(PluginResult.Status.OK, fileEntry); } catch (FileNotFoundException e) { JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, target, connection); Log.e(LOG_TAG, error.toString(), e); From a1d6fc07e8a40c1b2b16f4103c403b30e1089668 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Tue, 18 Feb 2014 20:58:31 -0500 Subject: [PATCH 09/17] Fix default value for trustAllHosts on iOS (YES->NO) --- src/ios/CDVFileTransfer.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ios/CDVFileTransfer.m b/src/ios/CDVFileTransfer.m index e35e2fe..c5c7502 100644 --- a/src/ios/CDVFileTransfer.m +++ b/src/ios/CDVFileTransfer.m @@ -255,7 +255,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) { NSString* source = [command.arguments objectAtIndex:0]; NSString* server = [command.arguments objectAtIndex:1]; - BOOL trustAllHosts = [[command.arguments objectAtIndex:6 withDefault:[NSNumber numberWithBool:YES]] boolValue]; // allow self-signed certs + BOOL trustAllHosts = [[command.arguments objectAtIndex:6 withDefault:[NSNumber numberWithBool:NO]] boolValue]; // allow self-signed certs NSString* objectId = [command.arguments objectAtIndex:9]; CDVFileTransferDelegate* delegate = [[CDVFileTransferDelegate alloc] init]; @@ -360,7 +360,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) DLog(@"File Transfer downloading file..."); NSString* source = [command.arguments objectAtIndex:0]; NSString* target = [command.arguments objectAtIndex:1]; - BOOL trustAllHosts = [[command.arguments objectAtIndex:2 withDefault:[NSNumber numberWithBool:YES]] boolValue]; // allow self-signed certs + BOOL trustAllHosts = [[command.arguments objectAtIndex:2 withDefault:[NSNumber numberWithBool:NO]] boolValue]; // allow self-signed certs NSString* objectId = [command.arguments objectAtIndex:3]; NSDictionary* headers = [command.arguments objectAtIndex:4 withDefault:nil]; From a588236cbdb3c81e2b38b8bfc036aa89520b28d5 Mon Sep 17 00:00:00 2001 From: Jan Pittner Date: Tue, 18 Feb 2014 20:44:48 +0100 Subject: [PATCH 10/17] CB-2190 Make backgroundTaskId apply to downloads as well. Move backgroundTaskId to the delegate. --- src/ios/CDVFileTransfer.h | 2 +- src/ios/CDVFileTransfer.m | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/ios/CDVFileTransfer.h b/src/ios/CDVFileTransfer.h index 1ce7abe..07feb85 100644 --- a/src/ios/CDVFileTransfer.h +++ b/src/ios/CDVFileTransfer.h @@ -53,7 +53,6 @@ extern NSString* const kOptionsKeyCookie; AndHttpStatus:(int)httpStatus AndBody:(NSString*)body; @property (readonly) NSMutableDictionary* activeTransfers; -@property (nonatomic, assign) UIBackgroundTaskIdentifier backgroundTaskID; @end @class CDVFileTransferEntityLengthRequest; @@ -65,6 +64,7 @@ extern NSString* const kOptionsKeyCookie; @property (strong) NSMutableData* responseData; // atomic @property (nonatomic, strong) NSDictionary* responseHeaders; +@property (nonatomic, assign) UIBackgroundTaskIdentifier backgroundTaskID; @property (nonatomic, strong) CDVFileTransfer* command; @property (nonatomic, assign) CDVFileTransferDirection direction; @property (nonatomic, strong) NSURLConnection* connection; diff --git a/src/ios/CDVFileTransfer.m b/src/ios/CDVFileTransfer.m index c5c7502..9125e2f 100644 --- a/src/ios/CDVFileTransfer.m +++ b/src/ios/CDVFileTransfer.m @@ -220,12 +220,6 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) CFStreamCreateBoundPair(NULL, &readStream, &writeStream, kStreamBufferSize); [req setHTTPBodyStream:CFBridgingRelease(readStream)]; - self.backgroundTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskID]; - self.backgroundTaskID = UIBackgroundTaskInvalid; - NSLog(@"Background task to upload media finished."); - }]; - [self.commandDelegate runInBackground:^{ if (CFWriteStreamOpen(writeStream)) { NSData* chunks[] = {postBodyBeforeFile, fileData, postBodyAfterFile}; @@ -334,6 +328,10 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) } CDVFileTransferDelegate* delegate = [self delegateForUploadCommand:command]; [NSURLConnection connectionWithRequest:req delegate:delegate]; + // sets a background task ID for the transfer object. + delegate.backgroundTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + [delegate cancelTransfer:delegate.connection]; + }]; if (activeTransfers == nil) { activeTransfers = [[NSMutableDictionary alloc] init]; @@ -410,6 +408,9 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) delegate.target = [targetURL absoluteString]; delegate.targetURL = targetURL; delegate.trustAllHosts = trustAllHosts; + delegate.backgroundTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + [delegate cancelTransfer:delegate.connection]; + }]; delegate.connection = [NSURLConnection connectionWithRequest:req delegate:delegate]; @@ -560,8 +561,8 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) [command.activeTransfers removeObjectForKey:objectId]; // remove background id task in case our upload was done in the background - [[UIApplication sharedApplication] endBackgroundTask:self.command.backgroundTaskID]; - self.command.backgroundTaskID = UIBackgroundTaskInvalid; + [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskID]; + self.backgroundTaskID = UIBackgroundTaskInvalid; } - (void)removeTargetFile @@ -574,6 +575,11 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) - (void)cancelTransfer:(NSURLConnection*)connection { [connection cancel]; + + CDVFileTransferDelegate* delegate = [self.command.activeTransfers objectForKey:self.objectId]; + [[UIApplication sharedApplication] endBackgroundTask:delegate.backgroundTaskID]; + delegate.backgroundTaskID = UIBackgroundTaskInvalid; + [self.command.activeTransfers removeObjectForKey:self.objectId]; [self removeTargetFile]; } From 49b4774e7ecea3730fb060eafd0c7d8b7e98523a Mon Sep 17 00:00:00 2001 From: Jan Pittner Date: Wed, 19 Feb 2014 10:56:27 -0500 Subject: [PATCH 11/17] CB-6059 iOS: Stop FileTransfer.download doing IO on the UI thread. --- src/ios/CDVFileTransfer.h | 1 + src/ios/CDVFileTransfer.m | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ios/CDVFileTransfer.h b/src/ios/CDVFileTransfer.h index 07feb85..ab95221 100644 --- a/src/ios/CDVFileTransfer.h +++ b/src/ios/CDVFileTransfer.h @@ -52,6 +52,7 @@ extern NSString* const kOptionsKeyCookie; AndTarget:(NSString*)target AndHttpStatus:(int)httpStatus AndBody:(NSString*)body; +@property (nonatomic, strong) NSOperationQueue* queue; @property (readonly) NSMutableDictionary* activeTransfers; @end diff --git a/src/ios/CDVFileTransfer.m b/src/ios/CDVFileTransfer.m index 9125e2f..27e1204 100644 --- a/src/ios/CDVFileTransfer.m +++ b/src/ios/CDVFileTransfer.m @@ -412,13 +412,19 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) [delegate cancelTransfer:delegate.connection]; }]; - delegate.connection = [NSURLConnection connectionWithRequest:req delegate:delegate]; + delegate.connection = [[NSURLConnection alloc] initWithRequest:req delegate:delegate startImmediately:NO]; + + if (self.queue == nil) { + self.queue = [[NSOperationQueue alloc] init]; + } + [delegate.connection setDelegateQueue:self.queue]; if (activeTransfers == nil) { activeTransfers = [[NSMutableDictionary alloc] init]; } - [activeTransfers setObject:delegate forKey:delegate.objectId]; + + [delegate.connection start]; } - (NSMutableDictionary*)createFileTransferError:(int)code AndSource:(NSString*)source AndTarget:(NSString*)target From 0f8467bdfe238bee5cd3af9545dfe152de12d65f Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Wed, 19 Feb 2014 11:49:24 -0500 Subject: [PATCH 12/17] CB-6059 iOS: Add necessary @synchronized blocks for newly introduced multi-threading. --- src/ios/CDVFileTransfer.m | 70 ++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/src/ios/CDVFileTransfer.m b/src/ios/CDVFileTransfer.m index 27e1204..9ba20e2 100644 --- a/src/ios/CDVFileTransfer.m +++ b/src/ios/CDVFileTransfer.m @@ -75,6 +75,10 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) @implementation CDVFileTransfer @synthesize activeTransfers; +- (void)pluginInitialize { + activeTransfers = [[NSMutableDictionary alloc] init]; +} + - (NSString*)escapePathComponentForUrlString:(NSString*)urlString { NSRange schemeAndHostRange = [urlString rangeOfString:@"://.*?/" options:NSRegularExpressionSearch]; @@ -327,29 +331,34 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) return; } CDVFileTransferDelegate* delegate = [self delegateForUploadCommand:command]; - [NSURLConnection connectionWithRequest:req delegate:delegate]; + delegate.connection = [[NSURLConnection alloc] initWithRequest:req delegate:delegate startImmediately:NO]; + if (self.queue == nil) { + self.queue = [[NSOperationQueue alloc] init]; + } + [delegate.connection setDelegateQueue:self.queue]; + // sets a background task ID for the transfer object. delegate.backgroundTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [delegate cancelTransfer:delegate.connection]; }]; - if (activeTransfers == nil) { - activeTransfers = [[NSMutableDictionary alloc] init]; + @synchronized (activeTransfers) { + activeTransfers[delegate.objectId] = delegate; } - - [activeTransfers setObject:delegate forKey:delegate.objectId]; + [delegate.connection start]; } - (void)abort:(CDVInvokedUrlCommand*)command { NSString* objectId = [command.arguments objectAtIndex:0]; - CDVFileTransferDelegate* delegate = [activeTransfers objectForKey:objectId]; - - if (delegate != nil) { - [delegate cancelTransfer:delegate.connection]; - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self createFileTransferError:CONNECTION_ABORTED AndSource:delegate.source AndTarget:delegate.target]]; - [self.commandDelegate sendPluginResult:result callbackId:delegate.callbackId]; + @synchronized (activeTransfers) { + CDVFileTransferDelegate* delegate = activeTransfers[objectId]; + if (delegate != nil) { + [delegate cancelTransfer:delegate.connection]; + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self createFileTransferError:CONNECTION_ABORTED AndSource:delegate.source AndTarget:delegate.target]]; + [self.commandDelegate sendPluginResult:result callbackId:delegate.callbackId]; + } } } @@ -419,10 +428,9 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) } [delegate.connection setDelegateQueue:self.queue]; - if (activeTransfers == nil) { - activeTransfers = [[NSMutableDictionary alloc] init]; + @synchronized (activeTransfers) { + activeTransfers[delegate.objectId] = delegate; } - [activeTransfers setObject:delegate forKey:delegate.objectId]; [delegate.connection start]; } @@ -467,13 +475,13 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) return result; } -- (void)onReset -{ - for (CDVFileTransferDelegate* delegate in [activeTransfers allValues]) { - [delegate.connection cancel]; +- (void)onReset { + @synchronized (activeTransfers) { + while ([activeTransfers count] > 0) { + CDVFileTransferDelegate* delegate = [activeTransfers allValues][0]; + [delegate cancelTransfer:delegate.connection]; + } } - - [activeTransfers removeAllObjects]; } @end @@ -564,11 +572,12 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) [self.command.commandDelegate sendPluginResult:result callbackId:callbackId]; // remove connection for activeTransfers - [command.activeTransfers removeObjectForKey:objectId]; - - // remove background id task in case our upload was done in the background - [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskID]; - self.backgroundTaskID = UIBackgroundTaskInvalid; + @synchronized (command.activeTransfers) { + [command.activeTransfers removeObjectForKey:objectId]; + // remove background id task in case our upload was done in the background + [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskID]; + self.backgroundTaskID = UIBackgroundTaskInvalid; + } } - (void)removeTargetFile @@ -581,12 +590,13 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) - (void)cancelTransfer:(NSURLConnection*)connection { [connection cancel]; + @synchronized (self.command.activeTransfers) { + CDVFileTransferDelegate* delegate = self.command.activeTransfers[self.objectId]; + [self.command.activeTransfers removeObjectForKey:self.objectId]; + [[UIApplication sharedApplication] endBackgroundTask:delegate.backgroundTaskID]; + delegate.backgroundTaskID = UIBackgroundTaskInvalid; + } - CDVFileTransferDelegate* delegate = [self.command.activeTransfers objectForKey:self.objectId]; - [[UIApplication sharedApplication] endBackgroundTask:delegate.backgroundTaskID]; - delegate.backgroundTaskID = UIBackgroundTaskInvalid; - - [self.command.activeTransfers removeObjectForKey:self.objectId]; [self removeTargetFile]; } From d28f85d7b054bb6d9fb577f94df2852ede75c2b1 Mon Sep 17 00:00:00 2001 From: lmnbeyond Date: Mon, 24 Feb 2014 11:14:16 +0800 Subject: [PATCH 13/17] Make it a priority to use filesystemName to create FileSystem object --- www/FileTransfer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/FileTransfer.js b/www/FileTransfer.js index d6690fe..fb3ff24 100644 --- a/www/FileTransfer.js +++ b/www/FileTransfer.js @@ -184,7 +184,7 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro entry.isFile = result.isFile; entry.name = result.name; entry.fullPath = result.fullPath; - entry.filesystem = new FileSystem(result.filesystem == window.PERSISTENT ? 'persistent' : 'temporary'); + entry.filesystem = new FileSystem(result.filesystemName || (result.filesystem == window.PERSISTENT ? 'persistent' : 'temporary')); successCallback(entry); } }; From e76deb20d562aa4c4a35f6f6a1c7e68a91bfaa71 Mon Sep 17 00:00:00 2001 From: lmnbeyond Date: Tue, 25 Feb 2014 10:34:11 +0800 Subject: [PATCH 14/17] ios:Get file plugin via commandDelegate to avoid using global file plugin directly. --- src/ios/CDVFileTransfer.h | 2 ++ src/ios/CDVFileTransfer.m | 15 +++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/ios/CDVFileTransfer.h b/src/ios/CDVFileTransfer.h index ab95221..aea9b2d 100644 --- a/src/ios/CDVFileTransfer.h +++ b/src/ios/CDVFileTransfer.h @@ -19,6 +19,7 @@ #import #import +#import "CDVFile.h" enum CDVFileTransferError { FILE_NOT_FOUND_ERR = 1, @@ -81,5 +82,6 @@ extern NSString* const kOptionsKeyCookie; @property (nonatomic, assign) BOOL trustAllHosts; @property (strong) NSFileHandle* targetFileHandle; @property (nonatomic, strong) CDVFileTransferEntityLengthRequest* entityLengthRequest; +@property (nonatomic, strong) CDVFile *filePlugin; @end; diff --git a/src/ios/CDVFileTransfer.m b/src/ios/CDVFileTransfer.m index 9ba20e2..f19bece 100644 --- a/src/ios/CDVFileTransfer.m +++ b/src/ios/CDVFileTransfer.m @@ -19,7 +19,6 @@ #import #import "CDVFileTransfer.h" -#import "CDVFile.h" #import "CDVLocalFilesystem.h" #import @@ -27,8 +26,6 @@ #import #import -extern CDVFile *filePlugin; - @interface CDVFileTransfer () // Sets the requests headers for the request. - (void)applyRequestHeaders:(NSDictionary*)headers toRequest:(NSMutableURLRequest*)req; @@ -265,6 +262,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) delegate.source = source; delegate.target = server; delegate.trustAllHosts = trustAllHosts; + delegate.filePlugin = [self.commandDelegate getCommandInstance:@"File"]; return delegate; } @@ -280,7 +278,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) if (sourceURL) { // Try to get a CDVFileSystem which will handle this file. // This requires talking to the current CDVFile plugin. - fs = [filePlugin filesystemForURL:sourceURL]; + fs = [[self.commandDelegate getCommandInstance:@"File"] filesystemForURL:sourceURL]; } if (fs) { [fs readFileAtURL:sourceURL start:0 end:-1 callback:^(NSData *fileData, NSString *mimeType, CDVFileError err) { @@ -381,7 +379,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) * Check here to see if it looks like the user passed in a raw filesystem path. (Perhaps they had the path saved, and were previously using it with the old version of File). If so, normalize it by removing empty path segments, and check with File to see if any of the installed filesystems will handle it. If so, then we will end up with a filesystem url to use for the remainder of this operation. */ target = [target stringByReplacingOccurrencesOfString:@"//" withString:@"/"]; - targetURL = [filePlugin fileSystemURLforLocalPath:target].url; + targetURL = [[self.commandDelegate getCommandInstance:@"File"] fileSystemURLforLocalPath:target].url; } else { targetURL = [NSURL URLWithString:target]; } @@ -417,6 +415,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) delegate.target = [targetURL absoluteString]; delegate.targetURL = targetURL; delegate.trustAllHosts = trustAllHosts; + delegate.filePlugin = [self.commandDelegate getCommandInstance:@"File"]; delegate.backgroundTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [delegate cancelTransfer:delegate.connection]; }]; @@ -528,7 +527,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) @implementation CDVFileTransferDelegate -@synthesize callbackId, connection = _connection, source, target, responseData, responseHeaders, command, bytesTransfered, bytesExpected, direction, responseCode, objectId, targetFileHandle; +@synthesize callbackId, connection = _connection, source, target, responseData, responseHeaders, command, bytesTransfered, bytesExpected, direction, responseCode, objectId, targetFileHandle, filePlugin; - (void)connectionDidFinishLoading:(NSURLConnection*)connection { @@ -562,7 +561,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) self.targetFileHandle = nil; DLog(@"File Transfer Download success"); - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[filePlugin makeEntryForURL:self.targetURL]]; + result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self.filePlugin makeEntryForURL:self.targetURL]]; } else { downloadResponse = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding]; result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[command createFileTransferError:CONNECTION_ERR AndSource:source AndTarget:target AndHttpStatus:self.responseCode AndBody:downloadResponse]]; @@ -643,7 +642,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) CDVFilesystemURL *sourceURL = [CDVFilesystemURL fileSystemURLWithString:self.target]; if (sourceURL && sourceURL.fileSystemName != nil) { // This requires talking to the current CDVFile plugin - NSObject *fs = [filePlugin filesystemForURL:sourceURL]; + NSObject *fs = [self.filePlugin filesystemForURL:sourceURL]; filePath = [fs filesystemPathForURL:sourceURL]; } else { // Extract the path part out of a file: URL. From ed24e210f4d781db17861319e9daa3ad89c9bd95 Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Thu, 27 Feb 2014 16:40:32 -0500 Subject: [PATCH 15/17] CB-6106: Ensure that nativeURL is used by file transfer download --- www/FileTransfer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/www/FileTransfer.js b/www/FileTransfer.js index fb3ff24..d842c5a 100644 --- a/www/FileTransfer.js +++ b/www/FileTransfer.js @@ -185,6 +185,7 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro entry.name = result.name; entry.fullPath = result.fullPath; entry.filesystem = new FileSystem(result.filesystemName || (result.filesystem == window.PERSISTENT ? 'persistent' : 'temporary')); + entry.nativeURL = result.nativeURL; successCallback(entry); } }; From b3369db9107c7b586c2a0f90e90da03c2eaa7e3b Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Thu, 27 Feb 2014 11:56:29 -0500 Subject: [PATCH 16/17] CB-6114 Updated version and RELEASENOTES.md for release 0.4.2 --- RELEASENOTES.md | 11 +++++++++++ plugin.xml | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 537f114..34da2ff 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -57,3 +57,14 @@ * CB-5658 Delete stale snapshot of plugin docs * Remove @1 designation from file plugin dependency until pushed to npm * CB-5466: Update to work with filesystem URLs + +### 0.4.2 (Feb 28, 2014) +* CB-6106 Ensure that nativeURL is used by file transfer download +* iOS: Fix default value for trustAllHosts on iOS (YES->NO) +* CB-6059 iOS: Stop FileTransfer.download doing IO on the UI thread. +* CB-5588 iOS: Add response headers to upload result +* CB-2190 iOS: Make backgroundTaskId apply to downloads as well. Move backgroundTaskId to the delegate. +* CB-6050 Android: Use instance method on actual file plugin object to get FileEntry to return on download +* CB-6000 Android: Nginx rejects Content-Type without a space before "boundary". +* CB-4907 Android: Close stream when we're finished with it +* CB-6022 Add backwards-compatibility notes to doc diff --git a/plugin.xml b/plugin.xml index d93cdac..30e9588 100644 --- a/plugin.xml +++ b/plugin.xml @@ -2,7 +2,7 @@ + version="0.4.2"> File Transfer Cordova File Transfer Plugin Apache 2.0 From 4d2c87350d2ddeb2bd895279df45a61c9e7ddfa4 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Thu, 27 Feb 2014 15:36:31 -0500 Subject: [PATCH 17/17] Add NOTICE file --- NOTICE | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 NOTICE diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..46fed23 --- /dev/null +++ b/NOTICE @@ -0,0 +1,8 @@ +Apache Cordova +Copyright 2012 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +This product includes a copy of OkHttp from: +https://github.com/square/okhttp