本文转载至 http://www.it165.net/pro/html/201403/10755.html
-
今天需要用AFNetworking实现断点续传的功能,但是在进行了一番研究之后,发现AFNetworking虽然支持下载文件的暂停和继续,但是程序重新启动后再次下载无法进行续传。网上有说可以通过AFDownloadRequestOperation这个AFNetworking的扩展库来实现重新启动后的续传,但是经过本人测试,这个库在最新的AFNetworking上会报错,无奈之下,参考他的代码,自己实现了一个,在这里分享给大家。
实现的代码如下:
01.
//获取已下载的文件大小
02.
- (unsigned
long
long
)fileSizeForPath:(NSString *)path {
03.
signed
long
long
fileSize =
0
;
04.
NSFileManager *fileManager = [NSFileManager
new
];
// default is not thread safe
05.
if
([fileManager fileExistsAtPath:path]) {
06.
NSError *error = nil;
07.
NSDictionary *fileDict = [fileManager attributesOfItemAtPath:path error:&error];
08.
if
(!error && fileDict) {
09.
fileSize = [fileDict fileSize];
10.
}
11.
}
12.
return
fileSize;
13.
}
14.
//开始下载
15.
- (
void
)startDownload {
16.
NSString *downloadUrl = @
"http://www.xxx.com/xxx.zip"
;
17.
NSString *cacheDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:
0
];
18.
NSString *downloadPath = [cacheDirectory stringByAppendingPathComponent:@
"xxx.zip"
];
19.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:downloadUrl]];
20.
//检查文件是否已经下载了一部分
21.
unsigned
long
long
downloadedBytes =
0
;
22.
if
([[NSFileManager defaultManager] fileExistsAtPath:downloadPath]) {
23.
//获取已下载的文件长度
24.
downloadedBytes = [self fileSizeForPath:downloadPath];
25.
if
(downloadedBytes >
0
) {
26.
NSMutableURLRequest *mutableURLRequest = [request mutableCopy];
27.
NSString *requestRange = [NSString stringWithFormat:@
"bytes=%llu-"
, downloadedBytes];
28.
[mutableURLRequest setValue:requestRange forHTTPHeaderField:@
"Range"
];
29.
request = mutableURLRequest;
30.
}
31.
}
32.
//不使用缓存,避免断点续传出现问题
33.
[[NSURLCache sharedURLCache] removeCachedResponseForRequest:request];
34.
//下载请求
35.
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
36.
//下载路径
37.
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:downloadPath append:YES];
38.
//下载进度回调
39.
[operation setDownloadProgressBlock:^(NSUInteger bytesRead,
long
long
totalBytesRead,
long
long
totalBytesExpectedToRead) {
40.
//下载进度
41.
float
progress = ((
float
)totalBytesRead + downloadedBytes) / (totalBytesExpectedToRead + downloadedBytes);
42.
}];
43.
//成功和失败回调
44.
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
45.
46.
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
47.
48.
}];
49.
[operation start];
50.
}
需要注意的是,此种写法仅适用于下载zip包,因为下载其他格式的文件有可能出现数据过多的情况。当文件已经下载完成时,再次调用该函数,无法判断文件是否已经下载完整,于是会再次下载,此时服务器会报416错,同时返回也会输出到文件中,使得文件大小异常。但是zip格式不受影响。