NSURLSessionDownloadTask 断点下载
#import "ViewController.h"
#import "ASIHTTPRequest.h"
#import <AFNetworking/AFNetworking.h>
@interface ViewController () <NSURLSessionDownloadDelegate>
@property (strong, nonatomic) NSURLSessionDownloadTask *resumableTask; // 可恢复的下载任务
@property (strong, nonatomic) NSURLSession *currentSession; // 当前会话
/* 用于可恢复的下载任务的数据 */
@property (strong, nonatomic) NSData *partialData;
@property (weak, nonatomic) IBOutlet UIProgressView *downloadingProgressView;
@property (weak, nonatomic) IBOutlet UILabel *currentProgress_label;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
AFHTTPRequestOperationManager *man = [AFHTTPRequestOperationManager manager];
}
/* 创建当前的session */
- (void)createCurrentSession {
NSURLSessionConfiguration *defaultConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
self.currentSession = [NSURLSession sessionWithConfiguration:defaultConfig delegate:self delegateQueue:nil];
self.currentSession.sessionDescription = @"fdfd";
}
- (IBAction)download:(id)sender {
if (!self.currentSession) {
[self createCurrentSession];
}
if (self.partialData) { // 如果是之前被暂停的任务,就从已经保存的数据恢复下载
self.resumableTask = [self.currentSession downloadTaskWithResumeData:self.partialData];
}
else { // 否则创建下载任务
NSString *imageURLStr = @"http://192.168.1.102/0701.zip";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageURLStr]];
self.resumableTask = [self.currentSession downloadTaskWithRequest:request];
}
[self.resumableTask resume];
self.partialData = nil;
}
- (IBAction)stop:(id)sender {
[self.resumableTask cancelByProducingResumeData:^(NSData *resumeData) {
// 如果是可恢复的下载任务,应该先将数据保存到partialData中,注意在这里不要调用cancel方法
self.partialData = resumeData;
self.resumableTask = nil;
NSLog(@"resumeData = %@", resumeData);
[resumeData writeToFile:@"/Users/Mac/Desktop/resumeData" atomically:YES];
}];
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
NSLog(@"location = %@", location);
// 设置文件的存放目标路径
NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSURL *documentsDirectoryURL = [NSURL fileURLWithPath:documentsPath];
NSURL *fileURL = [documentsDirectoryURL URLByAppendingPathComponent:[[downloadTask.response URL] lastPathComponent]];
// 如果该路径下文件已经存在,就要先将其移除,在移动文件
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:[fileURL path] isDirectory:NULL]) {
[fileManager removeItemAtURL:fileURL error:NULL];
}
[fileManager moveItemAtURL:location toURL:fileURL error:NULL];
}
/* 从fileOffset位移处恢复下载任务 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {
NSLog(@"NSURLSessionDownloadDelegate: Resume download at %lld", fileOffset);
}
/* 完成下载任务,无论下载成功还是失败都调用该方法 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
NSLog(@"NSURLSessionDownloadDelegate: Complete task");
NSLog(@"下载失败:%@", error);
}
/* 执行下载任务时有数据写入 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite // 期望收到的所有data字节数
{
// 计算当前下载进度并更新视图
double downloadProgress = totalBytesWritten / (double)totalBytesExpectedToWrite;
[self setDownloadProgress:downloadProgress];
}
/* 根据下载进度更新视图 */
- (void)setDownloadProgress:(double)progress {
NSString *progressStr = [NSString stringWithFormat:@"%.1f", progress * 100];
progressStr = [progressStr stringByAppendingString:@"%"];
NSLog(@"progressStr = %@", progressStr);
dispatch_async(dispatch_get_main_queue(), ^{
self.downloadingProgressView.progress = progress;
self.currentProgress_label.text = progressStr;
});
}
@end
[self.currentSession downloadTaskWithResumeData:self.partialData];
通过resumeData的原因如下是resumeData内容
resumeData内容如下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSURLSessionDownloadURL</key>
<string>http://192.168.1.102/0701.zip</string>
<key>NSURLSessionResumeBytesReceived</key>
<integer>47271936</integer>
<key>NSURLSessionResumeCurrentRequest</key>
<data>
YnBsaXN0MDDUAQIDBAUGcnNYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3AS
AAGGoK8QGAcIP0BGR05PUFFSU1Q1VVZiY2RlZmdobVUkbnVsbN8QGwkKCwwNDg8QERIT
FBUWFxgZGhscHR4fICEiIyQlJicoKSUrLC0nLycmJiYkNTYmOCY6Jjw9PlMkMTJSJDNT
JDI1UyQxN1IkNFMkMjFTJDEzViRjbGFzc1IkNVMkMThSJDZTJDIyUyQxNFIkN1MkMTlT
JDEwUiQ4UiQwUyQxNVMkMjNSJDlTJDExUiQxUyQyNFMkMTZSJDJTJDIwgAiAAoAAgAeA
A4AOgAKAF4AGgAyAB4APgAeAAIAAgACACBACgAqAAIAJgAAQCYAAgAsQFoANCNNBEEIm
REVXTlMuYmFzZVtOUy5yZWxhdGl2ZYAAgAWABF8QHWh0dHA6Ly8xOTIuMTY4LjEuMTAy
LzA3MDEuemlw0khJSktaJGNsYXNzbmFtZVgkY2xhc3Nlc1VOU1VSTKJMTVVOU1VSTFhO
U09iamVjdCNATgAAAAAAABAACREBhCMAAAAAAAAAACMAAAAAAAAAABP//////////1NH
RVTTV1gQWV1hV05TLmtleXNaTlMub2JqZWN0c6NaW1yAEIARgBKjXl9ggBOAFIAVgBZf
EA9BY2NlcHQtRW5jb2RpbmdWQWNjZXB0XxAPQWNjZXB0LUxhbmd1YWdlXWd6aXAsIGRl
ZmxhdGVTKi8qVWVuLXVz0khJaWpcTlNEaWN0aW9uYXJ5omtsXE5TRGljdGlvbmFyeVhO
U09iamVjdNJISW5vXE5TVVJMUmVxdWVzdKJwcVxOU1VSTFJlcXVlc3RYTlNPYmplY3Rf
EA9OU0tleWVkQXJjaGl2ZXLRdHVUcm9vdIABAAgAEQAaACMALQAyADcAUgBYAJEAlQCY
AJwAoACjAKcAqwCyALUAuQC8AMAAxADHAMsAzwDSANUA2QDdAOAA5ADnAOsA7wDyAPYA
+AD6APwA/gEAAQIBBAEGAQgBCgEMAQ4BEAESARQBFgEYARoBHAEeASABIgEkASYBKAEq
ASwBLQE0ATwBSAFKAUwBTgFuAXMBfgGHAY0BkAGWAZ8BqAGqAasBrgG3AcAByQHNAdQB
3AHnAesB7QHvAfEB9QH3AfkB+wH9Ag8CFgIoAjYCOgJAAkUCUgJVAmICawJwAn0CgAKN
ApYCqAKrArAAAAAAAAACAQAAAAAAAAB2AAAAAAAAAAAAAAAAAAACsg==
</data>
<key>NSURLSessionResumeEntityTag</key>
<string>"c04546-5c3ca3fe-5162cb9046b80"</string>
<key>NSURLSessionResumeInfoLocalPath</key>
<string>/Users/Mac/Library/Developer/CoreSimulator/Devices/E460928F-4469-41A7-B94E-8E6372A96C89/data/Containers/Data/Application/8E686354-BA1D-408E-8124-56AC07CD7287/tmp/CFNetworkDownload_brs2kY.tmp</string>
<key>NSURLSessionResumeInfoVersion</key>
<integer>1</integer>
<key>NSURLSessionResumeOriginalRequest</key>
<data>
YnBsaXN0MDDUAQIDBAUGTk9YJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3AS
AAGGoK4HCDM0OjtCQ0RFRkdISVUkbnVsbN8QFQkKCwwNDg8QERITFBUWFxgZGhscHR4f
ICEfIyQlICAoKCgeLC0uKDAxMlMkMTJSJDNTJDE3UiQ0UyQxM1YkY2xhc3NSJDVTJDE4
UiQ2UyQxNFIkN1MkMTlTJDEwUiQ4UiQwUyQxNVIkOVMkMTFSJDFTJDE2UiQygAiAAoAH
gAOAAoANgAaADIAHgAeAAIAAgACACBACgAqACYAAEAmACxAQCNM1DjYoODlXTlMuYmFz
ZVtOUy5yZWxhdGl2ZYAAgAWABF8QHWh0dHA6Ly8xOTIuMTY4LjEuMTAyLzA3MDEuemlw
0jw9Pj9aJGNsYXNzbmFtZVgkY2xhc3Nlc1VOU1VSTKJAQVVOU1VSTFhOU09iamVjdCNA
TgAAAAAAABAACREBgCMAAAAAAAAAACMAAAAAAAAAABP//////////9I8PUpLXE5TVVJM
UmVxdWVzdKJMTVxOU1VSTFJlcXVlc3RYTlNPYmplY3RfEA9OU0tleWVkQXJjaGl2ZXLR
UFFUcm9vdIABAAgAEQAaACMALQAyADcARgBMAHkAfQCAAIQAhwCLAJIAlQCZAJwAoACj
AKcAqwCuALEAtQC4ALwAvwDDAMYAyADKAMwAzgDQANIA1ADWANgA2gDcAN4A4ADiAOQA
5gDoAOoA7ADuAPAA8QD4AQABDAEOARABEgEyATcBQgFLAVEBVAFaAWMBbAFuAW8BcgF7
AYQBjQGSAZ8BogGvAbgBygHNAdIAAAAAAAACAQAAAAAAAABSAAAAAAAAAAAAAAAAAAAB
1A==
</data>
<key>NSURLSessionResumeServerDownloadDate</key>
<string>Sat, 16 May 2015 06:03:42 GMT</string>
</dict>
</plist>