You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ag...@apache.org on 2013/03/27 19:04:22 UTC
ios commit: [CB-2537] Implement streaming downloads for FileTransfer
Updated Branches:
refs/heads/master 3e007c35f -> d6a35768e
[CB-2537] Implement streaming downloads for FileTransfer
Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/d6a35768
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/d6a35768
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/d6a35768
Branch: refs/heads/master
Commit: d6a35768e74bda0e77a1bbe0aba8fcfe41c7b5c0
Parents: 3e007c3
Author: Ian Clelland <ic...@chromium.org>
Authored: Thu Mar 21 11:49:57 2013 -0400
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Wed Mar 27 14:04:00 2013 -0400
----------------------------------------------------------------------
CordovaLib/Classes/CDVFileTransfer.h | 1 +
CordovaLib/Classes/CDVFileTransfer.m | 87 +++++++++++++++++------------
2 files changed, 52 insertions(+), 36 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/d6a35768/CordovaLib/Classes/CDVFileTransfer.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVFileTransfer.h b/CordovaLib/Classes/CDVFileTransfer.h
index d82cdd3..404220b 100644
--- a/CordovaLib/Classes/CDVFileTransfer.h
+++ b/CordovaLib/Classes/CDVFileTransfer.h
@@ -70,5 +70,6 @@ extern NSString* const kOptionsKeyCookie;
@property (nonatomic, assign) NSInteger bytesTransfered;
@property (nonatomic, assign) NSInteger bytesExpected;
@property (nonatomic, assign) BOOL trustAllHosts;
+@property (strong) NSFileHandle* targetFileHandle;
@end;
http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/d6a35768/CordovaLib/Classes/CDVFileTransfer.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVFileTransfer.m b/CordovaLib/Classes/CDVFileTransfer.m
index 5741aca..9f14ef5 100644
--- a/CordovaLib/Classes/CDVFileTransfer.m
+++ b/CordovaLib/Classes/CDVFileTransfer.m
@@ -458,17 +458,14 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
@implementation CDVFileTransferDelegate
-@synthesize callbackId, connection, source, target, responseData, command, bytesTransfered, bytesExpected, direction, responseCode, objectId;
+@synthesize callbackId, connection = _connection, source, target, responseData, command, bytesTransfered, bytesExpected, direction, responseCode, objectId, targetFileHandle;
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
NSString* uploadResponse = nil;
NSString* downloadResponse = nil;
- BOOL downloadWriteOK = NO;
NSMutableDictionary* uploadResult;
CDVPluginResult* result = nil;
- NSError* __autoreleasing error = nil;
- NSString* parentPath;
BOOL bDirRequest = NO;
CDVFile* file;
@@ -491,40 +488,15 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
}
}
if (self.direction == CDV_TRANSFER_DOWNLOAD) {
- DLog(@"Write file %@", target);
- // error=[[NSError alloc]init];
-
- if ((self.responseCode >= 200) && (self.responseCode < 300)) {
- @try {
- parentPath = [self.target stringByDeletingLastPathComponent];
-
- // check if the path exists => create directories if needed
- if (![[NSFileManager defaultManager] fileExistsAtPath:parentPath]) {
- [[NSFileManager defaultManager] createDirectoryAtPath:parentPath withIntermediateDirectories:YES attributes:nil error:nil];
- }
-
- downloadWriteOK = [self.responseData writeToFile:self.target options:NSDataWritingFileProtectionNone error:&error];
-
- if (downloadWriteOK == NO) {
- // send our results back
- downloadResponse = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[command createFileTransferError:INVALID_URL_ERR AndSource:source AndTarget:target AndHttpStatus:self.responseCode AndBody:downloadResponse]];
- } else {
- DLog(@"File Transfer Download success");
-
- file = [[CDVFile alloc] init];
+ if (self.targetFileHandle) {
+ [self.targetFileHandle closeFile];
+ self.targetFileHandle = nil;
+ DLog(@"File Transfer Download success");
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[file getDirectoryEntry:target isDirectory:bDirRequest]];
- }
- }
- @catch(id exception) {
- // jump back to main thread
- downloadResponse = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsDictionary:[command createFileTransferError:FILE_NOT_FOUND_ERR AndSource:source AndTarget:target AndHttpStatus:self.responseCode AndBody:downloadResponse]];
- }
+ file = [[CDVFile alloc] init];
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[file getDirectoryEntry:target isDirectory:bDirRequest]];
} 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]];
}
}
@@ -535,9 +507,22 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
[command.activeTransfers removeObjectForKey:objectId];
}
+- (void)cancelTransferWithError:(NSURLConnection*)connection errorMessage:(NSString*)errorMessage
+{
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsDictionary:[self.command createFileTransferError:FILE_NOT_FOUND_ERR AndSource:self.source AndTarget:self.target AndHttpStatus:self.responseCode AndBody:errorMessage]];
+
+ NSLog(@"File Transfer Error: %@", errorMessage);
+ [connection cancel];
+ [self.command.activeTransfers removeObjectForKey:self.objectId];
+ [self.command.commandDelegate sendPluginResult:result callbackId:callbackId];
+}
+
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
+ NSError* __autoreleasing error = nil;
+
self.mimeType = [response MIMEType];
+ self.targetFileHandle = nil;
// required for iOS 4.3, for some reason; response is
// a plain NSURLResponse, not the HTTP subclass
@@ -554,6 +539,31 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
self.responseCode = 200;
self.bytesExpected = NSURLResponseUnknownLength;
}
+ if ((self.direction == CDV_TRANSFER_DOWNLOAD) && (self.responseCode >= 200) && (self.responseCode < 300)) {
+ // Download response is okay; begin streaming output to file
+ NSString* parentPath = [self.target stringByDeletingLastPathComponent];
+
+ // create parent directories if needed
+ if ([[NSFileManager defaultManager] createDirectoryAtPath:parentPath withIntermediateDirectories:YES attributes:nil error:&error] == NO) {
+ if (error) {
+ [self cancelTransferWithError:connection errorMessage:[NSString stringWithFormat:@"Could not create path to save downloaded file: %@", [error localizedDescription]]];
+ } else {
+ [self cancelTransferWithError:connection errorMessage:@"Could not create path to save downloaded file"];
+ }
+ return;
+ }
+ // create target file
+ if ([[NSFileManager defaultManager] createFileAtPath:self.target contents:nil attributes:nil] == NO) {
+ [self cancelTransferWithError:connection errorMessage:@"Could not create target file"];
+ return;
+ }
+ // open target file for writing
+ self.targetFileHandle = [NSFileHandle fileHandleForWritingAtPath:self.target];
+ if (self.targetFileHandle == nil) {
+ [self cancelTransferWithError:connection errorMessage:@"Could not open target file for writing"];
+ }
+ DLog(@"Streaming to file %@", target);
+ }
}
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
@@ -571,7 +581,11 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
self.bytesTransfered += data.length;
- [self.responseData appendData:data];
+ if (self.targetFileHandle) {
+ [self.targetFileHandle writeData:data];
+ } else {
+ [self.responseData appendData:data];
+ }
if (self.direction == CDV_TRANSFER_DOWNLOAD) {
BOOL lengthComputable = (self.bytesExpected != NSURLResponseUnknownLength);
@@ -618,6 +632,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
{
if ((self = [super init])) {
self.responseData = [NSMutableData data];
+ self.targetFileHandle = nil;
}
return self;
}