AFHTTPRequestOperation做文件下载的断点续传
2016-03-08 18:20
621 查看
之前自己单独做一个项目的时候第一次接触文件下载的断点续传功能,当时查找了很多博客和资料,由于第一次接触,使用了别人封装的一个工具类来做的,开发过程中发现会有一些问题,因为发生的几率不大,因此没有过多优化。当时找的工具类是基于AFNetworking写的,继承的AFHTTPRequestOperation类做的封装,提供了暂停喝继续的接口,也对父类的一些方法做了重写,当时就拿来用了,后来发现频繁点击暂停继续会使文件的游标出现错误,修改了一些类中的一些设置也只是降低触发的几率。
最近又需要做一个下载断点续传的功能,刚开始把之前的办法搬过来了,使用后发现还是会出现上述问题,于是上网再次开始查找资料,才发现AFHTTPRequestOperation本身对下载已经做好了任务,只需要在外部逻辑上修改自己需要的下载/暂停/继续/取消的逻辑就可以了,这里感谢http://blog.sina.com.cn/s/blog_a5d3d4490102w05m.html博主的博客。
下面是断点续传的代码,这里配合sqlite数据库进行下载进度及下载状态的读写。(代码仅供参考,因人懒只写了一些标注- -,也可以参考上面博客的内容)
最近又需要做一个下载断点续传的功能,刚开始把之前的办法搬过来了,使用后发现还是会出现上述问题,于是上网再次开始查找资料,才发现AFHTTPRequestOperation本身对下载已经做好了任务,只需要在外部逻辑上修改自己需要的下载/暂停/继续/取消的逻辑就可以了,这里感谢http://blog.sina.com.cn/s/blog_a5d3d4490102w05m.html博主的博客。
下面是断点续传的代码,这里配合sqlite数据库进行下载进度及下载状态的读写。(代码仅供参考,因人懒只写了一些标注- -,也可以参考上面博客的内容)
-(void)controlModelWithModel:(DownloadModel *)download_model andType:(NSString *)type{ NSString *md5 = download_model.model_md5_str; //下载 DownloadModel *model; BOOL hasModel = NO; DownloadListTable *table = (DownloadListTable *)[[DataBaseUtil shareInstance]getTableWithClass:[DownloadListTable class]]; for (DownloadModel *m in self.modelArr) { if ([m.model_md5_str isEqualToString:md5]) { model = m; hasModel = YES; } } if (!hasModel) { //列表中没有找到对应的模型 NSLog(@"error : not find model in arr"); return; } model.model_download_flag = @"1"; if (!model.model_download_percentage||[model.model_download_percentage isEqualToString:@"null"]) { model.model_download_percentage = @"0.00"; } //插入数据库表,如果存在则更新 [table insertTableWithConfition:model]; AppDelegate *app = [UIApplication sharedApplication].delegate; //读取全局保存的operation AFHTTPRequestOperation *operation = [app.downloadDic objectForKey:md5]; NSString *name = [NSString stringWithFormat:@"%@.%@",model.model_md5_str,model.model_format]; NSString *toPath = SAVE_MODEL_PATH(name); NSFileManager *fm = [NSFileManager defaultManager]; unsigned long long downloadedBytes = 0; //判断operation是否存在,不存在则创建 if (!operation) { NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:model.model_url]]; if ([fm fileExistsAtPath:toPath])//如果存在,说明有缓存文件 { downloadedBytes = [self fileSizeAtPath:toPath];//计算缓存文件的大小 NSMutableURLRequest *mutableURLRequest = [request mutableCopy]; NSString *requestRange = [NSString stringWithFormat:@"bytes=%llu-", downloadedBytes]; [mutableURLRequest setValue:requestRange forHTTPHeaderField:@"Range"]; request = mutableURLRequest; NSLog(@"==============断点下载"); } operation= [[AFHTTPRequestOperation alloc] initWithRequest:request]; [operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:toPath append:YES]]; [app.downloadDic setObject:operation forKey:md5]; } //设置进度操作 [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { float progress = ((float)totalBytesRead + downloadedBytes) / (totalBytesExpectedToRead + downloadedBytes); NSString *text = [NSString stringWithFormat:@"%.1f/%.1fM",((float)totalBytesRead + downloadedBytes)/1000/1000,(totalBytesExpectedToRead + downloadedBytes)/1000/1000.0]; NSLog(@"================downloadPrecent:%.2f size:%@",progress*100,text); //将进度保存到数据库文件中 if (![[DataBaseUtil shareInstance]isDataBaseInUse]) { model.model_download_percentage = [NSString stringWithFormat:@"%.2f",progress*100]; [table updateTableWithConfition:model]; } }]; [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject){ //计算/匹配 md5串 NSString *file_md5_str = [TRMD5 file_md5:toPath]; BOOL isRight = NO; if ([file_md5_str isEqualToString:md5]) { isRight = YES; } //如果md5匹配,则将数据保存,数据库修改为3下载完成 //如果不匹配,删掉下载文件,数据库删除该条数据 if (isRight) { //md5匹配成功,完成下载,下载缩略图并修改数据库信息 [self modelDownloadFinishedWithModel:model]; }else{ //md5匹配失败,删除文件 [table deleteTableWithConfition:model]; [fm removeItemAtPath:toPath error:nil]; } NSLog(@"downloadFinished"); } failure:^(AFHTTPRequestOperation *operation, NSError *error){ //下载失败的话删除文件,数据路信息 if (error.code == NSURLErrorCancelled || error.code == NSURLErrorNetworkConnectionLost) { //如果取消或网络连接断开,则不做处理,设置为暂停 }else{ [table deleteTableWithConfition:model]; [fm removeItemAtPath:toPath error:nil]; NSLog(@"downloadFail,errorCode:%@",error); } }]; //开始执行操作 switch ([type intValue]) { case 0://第一次下载 [operation start]; model.model_download_flag = @"1"; [table updateTableWithConfition:model]; break; case 1://暂停 [operation cancel]; operation = nil; [app.downloadDic removeObjectForKey:md5]; model.model_download_flag = @"2"; [table updateTableWithConfition:model]; break; case 2://继续下载 [operation start]; model.model_download_flag = @"1"; [table updateTableWithConfition:model]; break; case 3://下载完成的模型 break; default: break; } } //获取文件大小 -(unsigned long long)fileSizeAtPath:(NSString *)path{ signed long long fileSize = 0; NSFileManager *fileManager = [NSFileManager new]; if ([fileManager fileExistsAtPath:path]) { NSError *error = nil; NSDictionary *fileDict = [fileManager attributesOfItemAtPath:path error:&error]; if (!error && fileDict) { fileSize = [fileDict fileSize]; } }else{ fileSize = 0; } return fileSize; }
相关文章推荐
- Java网络编程(一)流
- 某某农业有限公司网络营销工作计划
- TCP性能优化
- TCP通信 ,Socket原理 ,服务端ServerSocket,客户端Socket
- Android网络通信之Socket
- 玩转OpenStack网络Neutron(2)--使用Open vSwitch实现VLAN类型租户网络
- 基于java的https双向认证,android上亦可用
- Tomcat配置https及访问http自动跳转至https
- Mybatis-Generator 详解 http://www.cnblogs.com/jtzfeng/p/5254798.html
- 对网络日志分析的几个方面
- Socket-TCP/UDP浅析
- mysql表数据发生变化时,主动通知业务系统(mysql-udf-http)
- Http协议
- php读取网络文件 curl, fsockopen ,file_get_contents 几个方法的效率对比
- php读取网络文件 curl, fsockopen ,file_get_contents 几个方法的效率对比
- iOS 开发 网络实时监测
- (3)下载网络文件
- TCP/IP 协议族概述
- ACE中TCP通信
- iOS 怎样通过UDP发送广播寻找设备,拿到ip地址,然后用TCP 连接设备