一、技术探讨:
NSOperationQueue 多线程池,自定义NSOperation任务队列,做本地视频文件下载业务处理。
1.downloadQueue 缓存视频线程池
2.沙盒缓存位置 webCache
3.NSOperation 任务
本地沙盒目录
//获取本地磁盘缓存文件夹路径
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,NSUserDomainMask,YES);
NSString *path = [paths lastObject];
NSString *diskCachePath = [NSString stringWithFormat:@"%@%@",path,@"/webCache"];
NSLog(@"\n%@",diskCachePath);
//判断是否创建本地磁盘缓存文件夹
BOOL isDirectory = NO;
BOOL isExisted = [[NSFileManager defaultManager] fileExistsAtPath:diskCachePath isDirectory:&isDirectory];
if (!isDirectory || !isExisted){
NSError *error;
[[NSFileManager defaultManager] createDirectoryAtPath:diskCachePath withIntermediateDirectories:YES attributes:nil error:&error];
}
//本地磁盘缓存文件夹URL
//开始下载任务
- (void)start {
[self willChangeValueForKey:@"isExecuting"];
_executing = YES;
[self didChangeValueForKey:@"isExecuting"];
//判断任务执行前是否取消了任务
if (self.isCancelled) {
[self done];
return;
}
@synchronized (self) {//加锁,等待代理完成
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForRequest = 15;
_session = [NSURLSession sessionWithConfiguration:sessionConfig
delegate:self
delegateQueue:NSOperationQueue.mainQueue];
self.task = [self.session downloadTaskWithRequest:self.request];
[self.task resume];
}
}
#pragma mark NSURLSessionDownloadDelegate -
//下载完成时调用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
self.fileName = downloadTask.response.suggestedFilename;
NSString *fullPath = [self.diskCachePath stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
if (![fullPath containsString:KVideoSuffix]) {
fullPath = [fullPath stringByAppendingString:KVideoSuffix];
}
[[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
HGLog(@"\n%s\n%@\n",__FUNCTION__,fullPath);
}
//网络资源下载请求完毕
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
if(_completedBlock) {
if(error) {
if (error.code == NSURLErrorCancelled) {
_cancelBlock(self.url);
[self done];
}else {
_completedBlock(self.url,error);
[self done];
}
}else {
self.completedBlock(self.url,nil);
[self done];
}
}
}
//跟踪下载进度
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
float progress = (float)totalBytesWritten/totalBytesExpectedToWrite;
NSLog(@"%f",progress);
}
//下载恢复(resume)时调用 Tells the delegate that the download task has resumed downloading.在调用downloadTaskWithResumeData:或者 downloadTaskWithResumeData:completionHandler: 方法之后这个代理方法会被调用
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes{
NSLog(@"%s------------fileOffset:%lld expectedTotalBytes:%lld", __func__,fileOffset,expectedTotalBytes);
}
@end