最近做云盤項目,必不可少的就是下載上傳,這里先介紹下載類的實現(xiàn),不過沒有用多線程下載,還有很多不足的地方請大家指出更正。
@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數(shù)據(jù)庫,對于線程要求很高就不再深究,有時間在回過頭來處理這個問題。
_session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]]
}
return _session;
}
//開始下載的方法
/*
*? 從0開始下載
*/
- (void)startDownload{
NSURL *url = self.path.jq_URL;//這里用了分類,實際上就是將path轉(zhuǎn)URL,這里的Path就是文件的下載路徑
//創(chuàng)建請求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//下載請求的方式,這個根據(jù)情況而定
[request setHTTPMethod:@"POST"];
//創(chuàng)建任務,這個task是因為會涉及到暫停,斷點續(xù)傳之類的要求
self.downloadTask = [self.session downloadTaskWithRequest:request];
//開始任務
[self.downloadTask resume];
}
/*
*? 暫停下載
*/
- (void)pause{
MJWeakSelf//這個是MJRefresh的weakSelf的宏定義
[self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
//resumeData:包含了繼續(xù)下載的開始位置和下載的url
//斷點續(xù)傳不僅客戶端要做,還需要服務端進行相應的適配才行。
weakSelf.resumeData = resumeData;
//置空task,resume的時候重新創(chuàng)建
weakSelf.downloadTask = nil;
}];
}
/*
*? 恢復下載
*/
- (void)resume{
//傳入暫停下載返回的數(shù)據(jù)
self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
//開始恢復下載
[self.downloadTask resume];
//清空上次返回數(shù)據(jù)
self.resumeData = nil;
}
//到這里已經(jīng)實現(xiàn)了基本的下載需求,不過對于項目肯定需要監(jiān)聽進度及其他一系列東西,這里要求我們滿足NSURLSessionDownloadDelegate協(xié)議,代理在config的時候已經(jīng)設置了
/**
*? 下載完畢會調(diào)用
*
*? @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];
//關(guān)閉定時器,這個定時器是用來計算每秒的下載速度
[self.timer invalidate];
}
/**
*? 每次寫入沙盒完畢調(diào)用
*? 在這里面監(jiān)聽下載進度,totalBytesWritten/totalBytesExpectedToWrite
*
*? @param bytesWritten? ? ? ? ? ? ? 這次寫入的大小
*? @param totalBytesWritten? ? ? ? 已經(jīng)寫入沙盒的大小
*? @param totalBytesExpectedToWrite 文件總大小
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
//建議判斷是否存在同名文件,方法不在列舉
參數(shù)說明已經(jīng)介紹的很詳細,具體要怎么操作根據(jù)實際需求做就好
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;//每秒清零一次
}
/**
*? 恢復下載后調(diào)用,
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{
//根據(jù)實際需求,在暫停后恢復下載可以做一定操作。
}
//結(jié)束介紹,歡迎大家提出意見,給予更新。