Objective-C检查下载的文件大小

时间:2011-02-18 09:08:32

标签: iphone objective-c download

我正在创建一个从S3服务器下载.zip文件的应用程序。 一切正常。现在我希望能够中断当前的下载。如果我可以保存文件的当前大小(字节),我将能够发送一个带有范围标题的新请求,用于文件的其他部分。

问题在于我无法确定“已经”下载内容的大小,因为我只能在下载完成时看到我目录中的文件。因此,如果我中断,则不会保存部分文件。

目前我使用以下代码:

 -(void) downloadFile:(NSMutableArray*)paramArray withDict:(NSMutableDictionary*)options
 {

NSLog(@"DOWNLOAD THREAD STARTED");
NSString * sourceUrl = [paramArray objectAtIndex:0];
NSString * fileName = [paramArray objectAtIndex:1];

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];    

NSString *newFilePath = [documentsDirectory stringByAppendingString:fileName];

NSError *error=[[[NSError alloc]init] autorelease]; 


NSURLConnection *fileURL = [NSData dataWithContentsOfURL: [NSURL URLWithString:sourceUrl]];

BOOL response = [fileURL writeToFile:newFilePath options:NSDataWritingFileProtectionNone error:&error]; 

if (response == TRUE)
{
    NSLog(@"DOWNLOAD COMPLETED");
    [self performSelectorOnMainThread:@selector(downloadComplete:withDict:) withObject:paramArray waitUntilDone:YES];
}
else 
{
    NSLog(@"Something went wrong while downloading file.");
    NSString *callback = [NSString stringWithFormat:@"downloadInterrupted('%@');",fileName];
    [webView stringByEvaluatingJavaScriptFromString:callback];

}

[pool drain];
}

AsiHTTP不是一个选项,因为我正在使用的PhoneGap存在问题。

3 个答案:

答案 0 :(得分:3)

更好的想法是异步下载文件。这有几个优点:最重要的一点是您的用户界面保持响应。用户可以在下载和等待数据时继续使用您的应用程序。如果您下载的数据对于应用程序绝对必要,请显示某种加载指示器。

您可以通过

轻松启动异步下载
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:sourceUrl]];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];

现在,如何在NSData对象中获取下载数据?您为self实现了以下委托方法:

-connection:didReceiveData:
-connection:didFailWithError:
-connectionDidFinishLoading:

我们的想法是,只要有些数据通过您的连接或其他重要事件发生(例如成功或失败),您就会收到通知。因此,您将声明一个临时NSMutableData对象作为实例变量(例如downloadData)并写入,直到下载完成。不要忘记初始化空对象并声明属性!

每当某种数据(即下载文件的一部分)到达时,都会调用

-connection:didReceiveData:。所以你要将它附加到你的临时对象上:

-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.downloadData appendData:data];
}

下载完成(成功)后,将调用下一个委托方法:

-(void) connectionDidFinishLoading:(NSURLConnection *)connection {
    //do whatever you need to do with the data in self.downloadData
}

如果下载失败,则会调用-connection:didFailWithError:。然后,您可以保存临时对象,获取其大小并稍后继续下载。 [self.downloadData length];获取对象中数据的字节大小。

答案 1 :(得分:1)

你将不得不使用较低级别的api。

时间阅读unix socket编程。 http://www.fortunecity.com/skyscraper/arpanet/6/cc.htm将是一个良好的开端。

这真的不会太难。诚实。

答案 2 :(得分:0)

我建议您构建一个每1,2 MB或更少保存数据块的方法,以便正确恢复下载并避免内存崩溃。 这是因为如果您在传输过程中出错,则可能是您的文件已损坏。

无论如何发送范围HTML标头非常简单

NSFileHandle *fileHandler = [NSFileHandle fileHandleForReadingAtPath:dataPreviouslySavedPath];
[fileHandler seekToEndOfFile];
unsigned long long int range = [fileHandler offsetInFile];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:downloadURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
[request setValue:[NSString stringWithFormat:@"bytes=%lli-", range] forHTTPHeaderField:@"Range"];

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

希望这对你有所帮助。