学习1:基本学习
- (void)downLoadImage{
// // 方案一:基于扩展库进行网络请求
// [image setImageWithURL:[NSURL URLWithString:@"https://www.weixiaolive.com/zb_users/upload/2023/02/202302221677076277413609.jpg"]];
//
/*
1)创建manager、配置manager、使用manager中的方法(GET、PUT、POST、DELETE等)
2)manager中的方法 调用 dataTaskWithHTTPMethod:方法构建task,然后执行task([dataTask resume];)
3)
*/
// 方案二:普通网络请求
// 1)创建AFHTTPSessionManager对象(创建的时候会被默认配置:session、Reachability、Security、Serialization等)
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
// 2)设置请求参数的序列化方式(有默认值,但是图片类型需要特殊说明AFImageResponseSerializer)
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFImageResponseSerializer serializer];
// 3)get方法请求数据
NSString *url = @"https://www.weixiaolive.com/zb_users/upload/2023/02/202302221677076277413609.jpg";
[manager GET:url parameters:nil headers:nil progress:^(NSProgress * _Nonnull downloadProgress) {
NSLog(@"获取过程中的处理");
// 注意主线程更新UI内容
dispatch_async(dispatch_get_main_queue(), ^{
self.progressView.progress = 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount;
});
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"获取成功的处理");
self.imageView.image = responseObject;
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"获取失败的处理");
}];
}
补充问题1:更新UI的API必须在主线程中调用:
如果不在主线程中调用根据UI的API,可能会报错

image.png
学习2:断点下载
/**
* downloadTask的懒加载
*/
- (NSURLSessionDataTask *)downloadTask {
if (!_downloadTask) {
// 1. 创建下载URL
NSURL *url = [NSURL URLWithString:@"https://www.cockos.com/licecap/licecap132.dmg"];
// 2. 创建request请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 设置HTTP请求头中的Range(只请求指定部分的实体)
NSString *range = [NSString stringWithFormat:@"bytes=%zd-", self.currentLength];
[request setValue:range forHTTPHeaderField:@"Range"];
__weak typeof(self) weakSelf = self;
// 3.1 调用manager中的dataTaskWithRequest方法构建downloadTask
_downloadTask = [self.manager dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
NSLog(@"dataTaskWithRequest");
// 设置完成回调(不然完成一次之后,下次就下载不了了)
// 清空长度
weakSelf.currentLength = 0;
weakSelf.fileLength = 0;
// 关闭fileHandle
[weakSelf.fileHandle closeFile];
weakSelf.fileHandle = nil;
}];
// 3.2 设置响应block(文件长度、文件路径、文件句柄、返回值)
[self.manager setDataTaskDidReceiveResponseBlock:^NSURLSessionResponseDisposition(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSURLResponse * _Nonnull response) {
NSLog(@"NSURLSessionResponseDisposition");
// 获得下载文件的总长度:请求下载的文件长度 + 当前已经下载的文件长度
weakSelf.fileLength = response.expectedContentLength + self.currentLength;
// 沙盒文件路径
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"licecap132.dmg"];
NSLog(@"File downloaded to: %@",path);
NSFileManager *manager = [NSFileManager defaultManager];
if (![manager fileExistsAtPath:path]) {
// 如果没有下载文件的话,就创建一个文件。如果有下载文件的话,则不用重新创建(不然会覆盖掉之前的文件)
[manager createFileAtPath:path contents:nil attributes:nil];
}
// 创建文件句柄
weakSelf.fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
/*
NSURLSessionResponseCancel:取消请求并关闭连接。
NSURLSessionResponseAllow:继续处理请求。
NSURLSessionResponseBecomeDownload:将请求转化为下载任务。
*/
// 允许处理服务器的响应,才会继续接收服务器返回的数据
return NSURLSessionResponseAllow;
}];
// 3.3 设置数据block(根据文件句柄来判断从哪里开始写)
[self.manager setDataTaskDidReceiveDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSData * _Nonnull data) {
NSLog(@"setDataTaskDidReceiveDataBlock");
// 指定数据的写入位置 -- 文件内容的最后面
[weakSelf.fileHandle seekToEndOfFile];
// 向沙盒写入数据
[weakSelf.fileHandle writeData:data];
// 拼接文件总长度
weakSelf.currentLength += data.length;
// 获取主线程,不然无法正确显示进度。
NSOperationQueue* mainQueue = [NSOperationQueue mainQueue];
[mainQueue addOperationWithBlock:^{
// 下载进度
if (weakSelf.fileLength == 0) {
weakSelf.progressView.progress = 0.0;
weakSelf.progressLabel.text = [NSString stringWithFormat:@"当前下载进度:00.00%%"];
} else {
weakSelf.progressView.progress = 1.0 * weakSelf.currentLength / weakSelf.fileLength;
weakSelf.progressLabel.text = [NSString stringWithFormat:@"当前下载进度:%.2f%%",100.0 * weakSelf.currentLength / weakSelf.fileLength];
}
}];
}];
}
return _downloadTask;
}
完整代码:DownloadLearn
bug记录:
- 100.04%:下载完成之后再点击下载,会导致下载进度变成100.04%,并且损坏下载的文件
目前想到的解决办法就是:根据progressView.progress来判断是否继续下载
(后续对这个bug有了更深刻的认知之后再补充解决办法吧。。)