现在我来介绍之前说过的用NSUrlSession批量下载的方法,用NSUrlSession下载文件,有两种方法,一是直接调用Block方法做下载后的处理,二是利用NSUrlSessionDelegate的一系列方法,做下载文件后的处理,这种方法的好处就是可以随时监测下载进度。但是一旦选择调用代理方法,就不能用Block的初始化方法初始化,因为如果有Block方法,那么就会走Block,不会走代理方法了,这点需要注意。现在上两种方法的代码:
NSURL*url=[NSURL URLWithString:stringcontent];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];
request.timeoutInterval=90.0;//设置请求超时为5秒
request.HTTPMethod=@"POST";//设置请求方法
// 下载文件
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDownloadTask *downLoadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error)
{
// 下载成功
downloadRight = @"success";
// 注意 location是下载后的临时保存路径, 需要将它移动到需要保存的位置
NSError *saveError;
// 创建一个自定义存储路径
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *dirPath = [cachePath stringByAppendingPathComponent:FileName];
//创建文件夹,把下载文件存到文件夹里
NSFileManager *fileManager = [NSFileManager defaultManager];
NSLog(@"文件夹路径:%@",dirPath);
if(![fileManager fileExistsAtPath:dirPath]){
[fileManager createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:nil];
}else{
//删除原文件夹,创建新文件夹
[fileManager removeItemAtPath:dirPath error:nil];
[fileManager createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:nil];
}
//保存下载的压缩包
NSString *savePath = [dirPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.zip",ContentName]];
NSURL *saveURL = [NSURL fileURLWithPath:savePath];
// 文件移动到cache路径中
[[NSFileManager defaultManager] moveItemAtURL:location toURL:saveURL error:&saveError];
if (!saveError)
{
NSLog(@"保存成功");
}
else
{
NSLog(@"saveError is %@", saveError.localizedDescription);
}
}
else
{
//下载失败
NSLog(@"error is : %@", error.localizedDescription);
}
}];
// 恢复线程, 启动任务
[downLoadTask resume];
block方法的有点就是存储文件取名字比较方便,可以直接写一个方法,把需要的参数传进来。但就是不能获取实时的下载进度。
下面是利用代理方法下载:
NSURL*url=[NSURL URLWithString:stringcontent];
NSURLSessionConfiguration*cfg = [NSURLSessionConfiguration defaultSessionConfiguration]; // 默认配置
NSURLSession*session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];
// 创建任务
NSURLSessionDownloadTask*downloadTask = [session downloadTaskWithURL:url];
// 开始任务
[downloadTask resume];
NSLog(@"下载开始时间:%@",[NSDate date]);
代理方法有:
#pragma mark - NSUrlSessionDegelate
// 下载过程中 会多次调用, 记录下载进度
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
// 记录下载进度
NSString * progress = [NSString stringWithFormat:@"%f",(double)totalBytesWritten/totalBytesExpectedToWrite];
self.progressLB.text = progress;
}
// 下载完成
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSString *filesName;
NSString *contentName;
NSDictionary *dict = self.downloadArray[downCount];
filesName = [NSString stringWithFormat:@"%@",dict[@"fileName"]];
contentName = [NSString stringWithFormat:@"%@",dict[@"contentName"]];
//通知 downCount++
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downCountJishu) name:@"notice" object:nil];
NSLog(@"%@",downloadTask.currentRequest.URL);
NSLog(@"下载完成时间:%@",[NSDate date]);
// 注意 location是下载后的临时保存路径, 需要将它移动到需要保存的位置
NSError *saveError;
// 创建一个自定义存储路径
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *dirPath = [cachePath stringByAppendingPathComponent:filesName];//downFileName
//创建文件夹,把下载文件存到文件夹里
NSFileManager *fileManager = [NSFileManager defaultManager];
NSLog(@"文件夹路径:%@",dirPath);
if(![fileManager fileExistsAtPath:dirPath]){
[fileManager createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:nil];
}else{
//删除原文件夹,创建新文件夹
[fileManager removeItemAtPath:dirPath error:nil];
[fileManager createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:nil];
}
//保存下载的压缩包
NSString *savePath = [dirPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.zip",contentName]];//downContentName
NSURL *saveURL = [NSURL fileURLWithPath:savePath];
// 文件移动到cache路径中
[[NSFileManager defaultManager] moveItemAtURL:location toURL:saveURL error:&saveError];
if (!saveError)
{
NSLog(@"保存成功");
//解压
[self jieyasuo:contentName :filesName];//downContentName,downFileName
}
else
{
NSLog(@"saveError is %@", saveError.localizedDescription);
}
[self performSelector:@selector(downCountJishu) withObject:nil];
}
- (void)downCountJishu
{
downCount ++;
}
// 当调用恢复下载的时候 触发的代理方法 [_downLoadTask resume]
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
}
#pragma mark --- 任务完成, 不管是否下载成功
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
if (error) {
//下载文件失败
}else{
//下载文件成功
}
}
#pragma mark --- session 后台下载完成 之后的操作 (本地通知 或者 更新UI)
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
{
}
注意,要记得遵守协议: NSURLSessionDownloadDelegate
在用代理方法下载文件时,我遇到的一个很多天都没有想到解决办法的问题,那就是在下载完成的代理方法里,由于系统方法无法把自己想要的参数传进去,所以保存文件的时候,我无法获取到所下载的文件究竟叫什么名字,从而给批量下载保存文件造成了困难。我查了很多网上的方法,都只说了在
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
的方法里,有一个属性是
response
.
suggestedFilename
这个是服务器保存的文件的名字,也是我们请求URL的最后一部分的字段,可以用它来当做下载文件的名字。如以下情况:
大部分人都可以用这个方法来解决保存文件的问题,但我的情况是:服务器把所有文件的请求路径都做成了一个,只不过每个文件下载时,传的一个filePath的参数都不一样,所以这给我保存时造成了很大的困难,我如果用上述方法,那么所有文件都会保存成同一个名字。
最后,我找到了一个解决办法,声明一个常量int downCount;先把downCount初始化为0,然后在下载完成的代理方法里,根据保存好的数组self.downloadArray和downCount获取对应的字典,然后获取下载的文件的相关信息,如fileName。再拼接保存文件的路径和名字就好了。每当保存好一个文件后,在代理方法的最后,将downCount++;这样downCount就像自动计数一样,将文件和下载内容对应起来了。
当然,这只是我想到的解决办法,希望大家如果有其他更好的办法,一起交流。
;