AFNetworking下载文件不走进度回调方法,文件确已下载好了,如何走进度回调?
原因
服务端开启了gzip压缩传输,没有Content-Length头部信息
无gzip压缩header
HTTP/1.1 200 OK
Date Wed, 22 May 2019 10:43:33 GMT
Server Apache/2.4.34 (Unix)
Last-Modified Wed, 22 May 2019 08:01:53 GMT
ETag "505825-5897560df9e40"
Accept-Ranges bytes
Content-Length 5265445
Keep-Alive timeout=5, max=100
Proxy-Connection keep-alive
有Content-Length 5265445
gzip压缩header
HTTP/1.1 200 OK
Date Wed, 22 May 2019 10:41:02 GMT
Server Apache/2.4.34 (Unix)
Last-Modified Tue, 21 May 2019 03:34:17 GMT
ETag "3016910-5895d86052040-gzip"
Accept-Ranges bytes
Vary Accept-Encoding
Content-Encoding gzip
Keep-Alive timeout=5, max=100
Content-Type application/zip
Proxy-Connection keep-alive
无Content-Length,有Content-Encoding gzip
为什么没有content-length
content-length含义
在HTTP协议中,Content-Length用于描述HTTP消息实体的传输长度the transfer-length of the message-body。在HTTP协议中,消息实体长度和消息实体的传输长度是有区别,比如说gzip压缩下,消息实体长度是压缩前的长度,消息实体的传输长度是gzip压缩后的长度。
解决方法三种
- 由于我的AFN版本是3.1.0,换其他版本,最好是新的
- 让服务端在其他接口返回下载文件的大小,已下载的大小能获取到,这样就可以知道进度了
- 文件请求接口先发送一个HEAD请求,并清空Accept-Encoding请求头字段,不接受Gzip压缩,从而获取到文件大小,
我的项目代码修改如下
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
// 构建SessionManager
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
// url 请求的接口
NSURL *URL = [NSURL URLWithString:url];
// 构建HEAD请求
NSMutableURLRequest *headRequest = [NSMutableURLRequest requestWithURL:URL];
[headRequest setHTTPMethod:@"HEAD"];
// 清空Accept-Encoding请求头字段,不接受Gzip压缩
[headRequest setValue:@"" forHTTPHeaderField:@"Accept-Encoding"];
NSURLSessionDataTask *headTask = [manager dataTaskWithRequest:headRequest
uploadProgress:nil
downloadProgress:nil
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
[manager setDownloadTaskDidWriteDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDownloadTask * _Nonnull downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
NSNumber *valNumber1 = [NSNumber numberWithLong:totalBytesWritten]; //下载的
NSNumber *valNumber2 = [NSNumber numberWithLong:response.expectedContentLength]; // 总的
// 显示小数 0-1进度 显示%进度 在x100
CGFloat value = valNumber1.floatValue/valNumber2.floatValue;
// 传值 到VC主线程刷新数据
progress(value);
}];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request
progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response){
// 上个接口拿到的destdir, 用于文件拼接
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
return [documentsDirectoryURL URLByAppendingPathComponent:[NSString stringWithFormat:@"%@/%@", destdir, [response suggestedFilename]]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
// 业务
if(error) {
NSLog(@"File downloaded error: %@", error);
fail(error);
} else {
NSLog(@"File downloaded to: %@", filePath);
succ(filePath.path);
}
}];
[downloadTask resume];
}];
[headTask resume];