我正在从Rackspace云文件下载mp3文件,对于大型文件,我遇到了下载成功完成但文件尚未完全下载的问题。例如,40 MB
mp3文件(01:00:00
持续时间)下载为4.5 MB
mp3文件(00:10:30
持续时间)。这不会一直发生。
以下是我创建和发送异步请求的方法:
ASIHTTPRequest *request;
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:urlString]];
[request setShouldAttemptPersistentConnection:NO];
[request setAllowResumeForFileDownloads:YES];
[request setDownloadProgressDelegate:self];
[request setShouldContinueWhenAppEntersBackground:YES];
[request setUserInfo:userInfo];
[request setDownloadDestinationPath:downloadPath];
[request setTemporaryFileDownloadPath:[NSString stringWithFormat:@"%@.download", downloadPath]];
[self.networkQueue addOperation:request];
[self.networkQueue go];
注意我正在使用具有4个并发下载的网络队列。
感谢。
编辑(2012年3月5日,星期三,下午03:25)
因此,进一步调查显示ASINetworkQueue
正在调用requestDidFinishSelector
委托方法而不是requestDidFailSelector
。 ASIHTTPRequest
对象返回的状态代码为206, HTTP/1.1 206 Partial Content
方法requestDidFinishSelector
。状态代码应为200, HTTP/1.1 200 OK
。
我还是不知道为什么!我仍然不知道如何解决这个问题。似乎我将不得不删除部分下载的文件并再次开始下载过程。此时,删除了临时文件%@.download
,并将此部分下载的文件放在目标路径中。
答案 0 :(得分:1)
所以,这就是我最终做的事情,希望这足够(解决问题)。
以下是我创建网络队列的方法:
- (ASINetworkQueue *)networkQueue {
if (!_networkQueue) {
_networkQueue = [[ASINetworkQueue alloc] init];
[_networkQueue setShowAccurateProgress:YES];
[_networkQueue setRequestDidFinishSelector:@selector(contentRequestDidSucceed:)];
[_networkQueue setRequestDidFailSelector:@selector(contentRequestDidFail:)];
[_networkQueue setShouldCancelAllRequestsOnFailure:NO];
[_networkQueue setDelegate:self];
}
return _networkQueue;
}
这就是我的contentRequestDidSucceed:
方法所做的事情:
- (void)contentRequestDidSucceed:(ASIHTTPRequest *)request {
// ASIHTTPRequest doesn't use HTTP status codes (except for redirection),
// so it's up to us to look out for problems (ex: 404) in the requestDidFinishSelector selector.
// requestDidFailSelector will be called only if there is the server can not be reached
// (time out, no connection, connection interrupted, ...)
// In certain cases ASIHTTPRequest/ASINetworkQueue calls the delegate method requestDidFinishSelector,
// instead it should call requestDidFailSelector. I've encountered this specific case with status code 206 (HTTP/1.1 206 Partial Content). In this case the file was not completely downloaded, so we'll have to re-process the request.
if ([request responseStatusCode] != 200) {
NSLog(@" ");
NSLog(@"======= BEEP =======");
NSLog(@" ");
// We're double checking that the file was indeed not downloaded completely!
// During internal testing, we encountered a case where download was successful
// but we received 206 as the response code (maybe we received the cached value).
unsigned long long progress = [request totalBytesRead] + [request partialDownloadSize];
unsigned long long total = [request contentLength] + [request partialDownloadSize];
if (progress != total) {
NSString *downloadPath = [request downloadDestinationPath];
NSString *temporaryDownloadPath = [self temporaryPathForFile:downloadPath];
// Move the file at destination path to the temporary destination path (back again)
NSError *moveError = nil;
[[[[NSFileManager alloc] init] autorelease] moveItemAtPath:downloadPath
toPath:temporaryDownloadPath
error:&moveError];
if (moveError) {
NSLog(@"Failed to move file from '%@' to '%@'", downloadPath, temporaryDownloadPath);
NSError *removeError = nil;
[ASIHTTPRequest removeFileAtPath:downloadPath error:&removeError];
if (removeError) {
NSLog(@"Failed to remove file from '%@'", downloadPath);
}
}
// Call the requestDidFailSelector method
[self contentRequestDidFail:request];
// Don't continue
return;
}
}
// TODO: Process successful request!
// . . .
}
如果有更好的方法来解决这个问题,请告诉我。