简单点说,content-length表示被下载文件的字节数。
对比原理讲解的第三步,我们可以看到如果要计算出文件的总字节数,那么必须把已经下载的字节数 加上 content-length。
我们需要把每个被下载文件的总字节数存储起来,这里我们选择使用plist文件来记载,plist文件包含一个字典。设置文件名为键值,已经下载的文件字节数为值。
文件名为了防止重复,这里我们设置文件名为下载url的hash值,可以保证不重重。
实现代码如下:
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSHTTPURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
self.totalLength = [response.allHeaderFields[@"Content-Length"] integerValue] + DownloadLength;
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile: TotalLengthPlist];
if (dict == nil) dict = [NSMutableDictionary dictionary];
dict[ Filename] = @(self.totalLength);
[dict writeToFile: TotalLengthPlist atomically:YES];
}
上述NSSessionDelegate方法会在请求收到回应的时候调用一次,我们可以在该方法中获取回应信息,取出content-length字段。
3.封装一个方法,实现下载进度,成功,失败提示
我们可以模仿AFNetwork,把下载封装到一个方法,然后使用不同的block来实现下载进度,成功,失败后的回调。
定义如下:
-(void)downLoadWithURL:(NSString *)URL
progress:(progressBlock)progressBlock
success:(successBlock)successBlock
faile:(faileBlock)faileBlock
{
self.successBlock = successBlock;
self.failedBlock = faileBlock;
self.progressBlock = progressBlock;
self.downLoadUrl = URL;
[self.task resume];
}
上面的三个block都采用宏定义方式,这样看起来比较简洁,具体代码参考下面的完整代码。
然后我们可以在NSURLSessionDataDelegate的对应的代理方法中去实现三个block的调用,然后传入相应的参数。这样当其他人调用我们的方法,就可以在相应的block中实现回调。具体代码参考下面的完整代码
完整代码实现
下面是完整的代码实现
#import <Foundation/Foundation.h>
typedef void (^successBlock) (NSString *fileStorePath);
typedef void (^faileBlock) (NSError *error);
typedef void (^progressBlock) (float progress);
@interface DownLoadManager : NSObject <NSURLSessionDataDelegate>
@property (copy) successBlock successBlock;
@property (copy) faileBlock failedBlock;
@property (copy) progressBlock progressBlock;
-(void)downLoadWithURL:(NSString *)URL
progress:(progressBlock)progressBlock
success:(successBlock)successBlock
faile:(faileBlock)faileBlock;
+ (instancetype)sharedInstance;
-(void)stopTask;
@end










