我正在创建一个从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存在问题。
答案 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];
希望这对你有所帮助。