最近做云盘项目,必不可少的就是下载上传,这里先介绍下载类的实现,不过没有用多线程下载,还有很多不足的地方请大家指出更正。
@property (nonatomic, strong) NSURLSessionDownloadTask* downloadTask;
/**
* resumeData记录下载位置
*/
@property (nonatomic, strong) NSData* resumeData;
@property (nonatomic, strong) NSURLSession* session;//SESSION对象是肯定要有的
对session就是懒加载
- (NSURLSession *)session{
if (!_session) {
NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];
//这里的queue其实还可以进一步细化,不过项目很赶就没做了,再加上使用了realm数据库,对于线程要求很高就不再深究,有时间在回过头来处理这个问题。
_session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]]
}
return _session;
}
//开始下载的方法
/*
* 从0开始下载
*/
- (void)startDownload{
NSURL *url = self.path.jq_URL;//这里用了分类,实际上就是将path转URL,这里的Path就是文件的下载路径
//创建请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//下载请求的方式,这个根据情况而定
[request setHTTPMethod:@"POST"];
//创建任务,这个task是因为会涉及到暂停,断点续传之类的要求
self.downloadTask = [self.session downloadTaskWithRequest:request];
//开始任务
[self.downloadTask resume];
}
/*
* 暂停下载
*/
- (void)pause{
MJWeakSelf//这个是MJRefresh的weakSelf的宏定义
[self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
//resumeData:包含了继续下载的开始位置和下载的url
//断点续传不仅客户端要做,还需要服务端进行相应的适配才行。
weakSelf.resumeData = resumeData;
//置空task,resume的时候重新创建
weakSelf.downloadTask = nil;
}];
}
/*
* 恢复下载
*/
- (void)resume{
//传入暂停下载返回的数据
self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
//开始恢复下载
[self.downloadTask resume];
//清空上次返回数据
self.resumeData = nil;
}
//到这里已经实现了基本的下载需求,不过对于项目肯定需要监听进度及其他一系列东西,这里要求我们满足NSURLSessionDownloadDelegate协议,代理在config的时候已经设置了
/**
* 下载完毕会调用
*
* @param location 文件临时地址
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
//保存至cache,方便清楚缓存
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// response.suggestedFilename : 建议使用的文件名,一般跟服务器端的文件名一致
NSString *file = [caches stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
// 将临时文件剪切或者复制Caches文件夹
NSFileManager *mgr = [NSFileManager defaultManager];
// AtPath : 剪切前的文件路径
// ToPath : 剪切后的文件路径
[mgr moveItemAtPath:location.path toPath:file error:nil];
//关闭定时器,这个定时器是用来计算每秒的下载速度
[self.timer invalidate];
}
/**
* 每次写入沙盒完毕调用
* 在这里面监听下载进度,totalBytesWritten/totalBytesExpectedToWrite
*
* @param bytesWritten 这次写入的大小
* @param totalBytesWritten 已经写入沙盒的大小
* @param totalBytesExpectedToWrite 文件总大小
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
//建议判断是否存在同名文件,方法不在列举
参数说明已经介绍的很详细,具体要怎么操作根据实际需求做就好
self.spead += bytesWritten;//这里将开启定时器,计算速度
if (!self.isBegin) {
self.timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(calculateSpead) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:(NSRunLoopCommonModes)];
self.isBegin = YES;
}
}
- (void)calculateSpead{
NSLog(@"%@",self.spead);
self.spead = 0;//每秒清零一次
}
/**
* 恢复下载后调用,
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{
//根据实际需求,在暂停后恢复下载可以做一定操作。
}
//结束介绍,欢迎大家提出意见,给予更新。