最近学习ASIHTTPRequest如何使用,所以利用ASIHTTPRequest自身的功能,写了个可断点下载的小demo
我利用tableview作为下载列表,所有自己custom了一个cell,用来控制下载
enum DownloadStatus {
DownloadNotStart = 0,
Downloading,
DownloadPause,
DownloadFinish
};
@interface DownloadFileListTableViewCell : UITableViewCell <ASIHTTPRequestDelegate, ASIProgressDelegate>{
UIProgressView *_progressView;
UIButton *_controlButton;
UILabel *_sizeTip;
ASIHTTPRequest *_asiRequest;
NSURL *_oriURL;
enum DownloadStatus _downloadStatus;
NSString *_saveFilePath;
NSString *_tmpFilePath;
long long _curSize;
long long _totalSize;
}
最新的 ASIHTTPRequest 自己有一个支持断点下载的方法,
[_asiRequest setTemporaryFileDownloadPath:_tmpFilePath];
[_asiRequest setAllowResumeForFileDownloads:YES];
只要设置了这两个,就可以实现断点下载
下面是我自己实现的几个控制下载的方法
- (void)startDownload
{
_curSize = 0;
_totalSize = 0;
_asiRequest = [[ASIHTTPRequest alloc] initWithURL:_oriURL];
[_asiRequest setDelegate:self];
[_asiRequest setDownloadProgressDelegate:self];
[_asiRequest setShowAccurateProgress:YES];
[_asiRequest setDownloadDestinationPath:_saveFilePath];
[_asiRequest setTemporaryFileDownloadPath:_tmpFilePath];
[_asiRequest setAllowResumeForFileDownloads:YES];
_downloadStatus = Downloading;
[_controlButton setTitle:@"Pause" forState:UIControlStateNormal];
[_asiRequest startAsynchronous];
}
- (void)pauseDownload
{
[_asiRequest clearDelegatesAndCancel];
[_asiRequest release], _asiRequest = nil;
_downloadStatus = DownloadPause;
[_controlButton setTitle:@"Resume" forState:UIControlStateNormal];
}
- (void)resumeDownload
{
_curSize = 0;
_asiRequest = [[ASIHTTPRequest alloc] initWithURL:_oriURL];
[_asiRequest setDelegate:self];
[_asiRequest setDownloadProgressDelegate:self];
[_asiRequest setShowAccurateProgress:YES];
[_asiRequest setDownloadDestinationPath:_saveFilePath];
[_asiRequest setTemporaryFileDownloadPath:_tmpFilePath];
[_asiRequest setAllowResumeForFileDownloads:YES];
_downloadStatus = Downloading;
[_controlButton setTitle:@"Pause" forState:UIControlStateNormal];
[_asiRequest startAsynchronous];
}
- (void)finishDownload
{
[_controlButton setTitle:@"Finish" forState:UIControlStateNormal];
_downloadStatus = DownloadFinish;
NSLog(@"success Finish Download");
}
因为要利用progressview手动记录下载情况,所以,继承了ASIProgressDelegate,并实现了
- (void)request:(ASIHTTPRequest *)request didReceiveBytes:(long long)bytes
{
// when resume download, the bytes is the size of the file which had down
_curSize += bytes;
float value = (_curSize*1.0)/(_totalSize*1.0);
[_progressView setProgress:value];
float tmp = 1024*1024.0;
NSString *tip = [NSString stringWithFormat:@"%.1lf/%.1lfM", _curSize/tmp, _totalSize/tmp];
[_sizeTip setText:tip];
}
这样,就可以随时记录下载情况了.
写这个demo的过程中,还遇到了url redirect的问题,ASIHTTPRequest本身是可以auto redirect的,但是不知什么原因,我这里并没有auto redirect,所以,我自己手动控制它redirect(实现ASIHTTPRequestDelegate的requestFailed方法)
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
[_controlButton setTitle:@"Fail" forState:UIControlStateNormal];
NSLog(@"Failed error : %@", [error localizedDescription]);
NSDictionary *resp = [request responseHeaders];
NSString *redirectURL = [resp valueForKey:@"Location"];
if([request responseStatusCode] == 302 && redirectURL){
[self redirectToDest:redirectURL];
}
}
当然,status code = 301的时候也需要redirect,我这里就没加上了.
到这里,我还遇到个问题就是,每次下载都定死了文件名,当下载多个文件时,会导致文件重写,所以,要时不同文件不重复,且能很好的辨认,最后的办法就是能从头部中获取服务端返回的文件名,并以此命名.但是,在ASIHTTPRequet的responseHeader中却找不到这个值.经google后得知,需要自己解析header 的 Content-Disposition.所以,我想获取ASIHTTPRequest刚获取的header,不知怎么获取.