使用NSURLConnection实现大文件断点下载

由于是实现大文件的断点下载,不是下载一般图片什么的.在设计这个类的时候本身就不会考虑把下载的文件缓存到内存中,而是直接写到文件系统.

要实现断点下载,需要满足1个条件,那就是,必须要服务器支持断点下载.

实现的思路是这样子的:

1.  第一次会获取到被下载文件的总大小(服务器提供这个值)

  下载文件总大小 = 期望从服务器获取文件的大小 + 本地已经下载的文件的大小

2.  设置请求的缓存策略为不会读取本地中已经缓存的数据(NSURLRequestReloadIgnoringLocalCacheData)

3.  在去服务器请求数据之前先获取到本地已经下载好的部分文件的长度,以这个参数设置进Range中到服务器去请求剩下的数据

4.  当从网络获取到一定的数据的时候,我们直接将数据写进文件系统中

YXDownloadNetwork.h

//
//  YXDownloadNetwork.h
//  Download
//
//  http://home.cnblogs.com/u/YouXianMing/
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//#import <Foundation/Foundation.h>// block的相关定义
typedef void (^downloadProgress_t)(long long currentBytes, long long totalBytes);
typedef void (^completion_t)(NSDictionary *headers, NSData *body);@interface YXDownloadNetwork : NSObject// 将block定义成属性
@property (nonatomic, copy) downloadProgress_t       downloadProgress;
@property (nonatomic, copy) completion_t             completion;// 初始化方法
- (instancetype)initWithUrlString:(NSString *)urlString cacheCapacity:(unsigned long long)capacity;
- (void)start;@end

YXDownloadNetwork.m

//
//  YXDownloadNetwork.m
//  Download
//
//  http://home.cnblogs.com/u/YouXianMing/
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//#import "YXDownloadNetwork.h"@interface YXDownloadNetwork ()<NSURLConnectionDelegate, NSURLConnectionDataDelegate>@property (nonatomic, assign) unsigned long long   totalLength;      // 文件总大小
@property (nonatomic, assign) unsigned long long   startDataLength;  // 本地存在文件的大小
@property (nonatomic, assign) unsigned long long   expectedLength;   // 从服务器期望文件的大小
@property (nonatomic, assign) unsigned long long   cacheCapacity;    // 缓存文件容量,以k为单位@property (nonatomic, strong) NSURLConnection     *dataConncetion;   // 网络连接
@property (nonatomic, strong) NSDictionary        *responseHeaders;  // 网络连接头部信息
@property (nonatomic, strong) NSFileHandle        *file;             // 文件操作句柄
@property (nonatomic, strong) NSMutableData       *cacheData;        // 用于缓存的data数据@end@implementation YXDownloadNetwork- (instancetype)initWithUrlString:(NSString *)urlString cacheCapacity:(unsigned long long)capacity
{self = [super init];if (self){// 获取缓存容量if (capacity <= 0){_cacheCapacity = 100 * 1024;}else{_cacheCapacity = capacity * 1024;}// 获取用于缓存的数据_cacheData = [NSMutableData new];// 获取文件名以及文件路径NSString *fileName = [urlString lastPathComponent];NSString *filePath = \fileFromPath([NSString stringWithFormat:@"/Documents/%@", fileName]);// 记录文件起始位置if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]){// 从文件中读取出已经下载好的文件的长度_startDataLength = [[NSData dataWithContentsOfFile:filePath] length];}else{// 不存在则创建文件_startDataLength = 0;[[NSFileManager defaultManager] createFileAtPath:filePathcontents:nilattributes:nil];}// 打开写文件流_file = [NSFileHandle fileHandleForWritingAtPath:filePath];// 创建一个网络请求NSMutableURLRequest* request = \[NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];// 禁止读取本地缓存[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];// 设置断点续传(需要服务器支持)[request setValue:[NSString stringWithFormat:@"bytes=%llu-", _startDataLength]forHTTPHeaderField:@"Range"];// 开始创建连接self.dataConncetion = \[[NSURLConnection alloc] initWithRequest:requestdelegate:selfstartImmediately:NO];}return self;
}- (void)start
{[self.dataConncetion start];
}- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{if([response isKindOfClass:[NSHTTPURLResponse class]]){NSHTTPURLResponse *r = (NSHTTPURLResponse *)response;// 如果能获取到期望的数据长度就执行括号中的方法if ([r expectedContentLength] != NSURLResponseUnknownLength){// 获取剩余要下载的_expectedLength  = [r expectedContentLength];// 计算出总共需要下载的_totalLength = _expectedLength + _startDataLength;// 获取头文件_responseHeaders = [r allHeaderFields];}else{NSLog(@"不支持断点下载");}}
}- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData
{// 追加缓存数据[_cacheData appendData:theData];// 如果该缓存数据的大小超过了指定的缓存大小if ([_cacheData length] >= _cacheCapacity){// 移动到文件结尾[_file seekToEndOfFile];// 在文件末尾处追加数据[_file writeData:_cacheData];// 清空缓存数据[_cacheData setLength:0];}// 当前已经下载的所有数据的总量_startDataLength += [theData length];// 如果指定了blockif (_downloadProgress){_downloadProgress(_startDataLength, _totalLength);}
}- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{// 移动到文件结尾[_file seekToEndOfFile];// 在文件末尾处追加最后的一点缓存数据[_file writeData:_cacheData];// 清空缓存[_cacheData setLength:0];NSLog(@"下载完成哦");
}NS_INLINE NSString * fileFromPath(NSString *filePath)
{return [NSHomeDirectory() stringByAppendingString:filePath];
}@end

测试代码如下:

实际上这个类还有很多地方不完善,但至少能起到抛砖引玉的作用,它更牛逼的用途靠你来修改了,亲.

使用NSURLConnection实现大文件断点下载相关推荐

  1. iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载

    前言:iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载是在前篇iOS开发之网络编程--使用NSURLConnection实现大文件下载的基础上进行    断点续传的设置 ...

  2. SpringBoot+Vue 实现大文件断点下载

    目录 效果 代码 SpringBoot Vue 效果 步骤 点击下载 在输入框输入下载的文件名称 点击暂停 再次点击开始 下载完成 代码 SpringBoot pom <!-- 做断点下载使用- ...

  3. Retrofit 2.0 超能实践(四),完成大文件断点下载

    作者:码小白 文/CSDN 博客 本文出自:http://blog.csdn.net/sk719887916/article/details/51988507 码小白 通过前几篇系统的介绍和综合运用, ...

  4. Akka实战:HTTP大文件断点上传、下载,秒传

    2019独角兽企业重金招聘Python工程师标准>>> 访问:https://github.com/yangbajing/scala-applications/tree/master ...

  5. Linux命令行下载大文件,下载Onedrive文件

    Linux命令行下载大文件,下载Onedrive文件 做深度学习实验时,经常会遇到下载数据集,下载到本地又上传到Linux服务器上,这时用rz上传会很慢,在网上找到一些方法,用curl下载One-dr ...

  6. 实现微信小程序web-view内嵌H5中的下载功能(大文件切片下载)

    实现微信小程序内嵌H5中的下载功能 一.项目场景: 难点 解决方案: 1.H5微信小程序: a.首先必不可少的是安装jweixin-module模块: b.在main.js中将依赖绑定: c.H5对应 ...

  7. JavaScript 中如何实现大文件并行下载?

    在 JavaScript 中如何实现并发控制? 这篇文章中,阿宝哥详细分析了 async-pool 这个库如何利用 Promise.all 和 Promise.race 函数实现异步任务的并发控制.本 ...

  8. Java实现大文件多线程下载,提速30倍!想学?我教你啊

    前言 在上一篇文章 <面试官不讲武德>对Java初级程序猿死命摩擦Http协议 中,我们有提到大文件下载和断点续传,本篇我们就来开发一个多线程文件下载器,最后我们用这个多线程下载器来突破云 ...

  9. NSURLSessionDataTask与NSOperationQueue实现多文件断点下载(任意时刻终止进程,重启应用,自动重启下载)...

    效果展示 gif有点大,直接连接:7qnbrb.com1.z0.glb.clouddn.com/download.gi- 知识要点 NSOperationQueue线程队列的管理 NSURLSessi ...

最新文章

  1. Invalid syntax for function signature in TLD
  2. linux下eclipse cdt引用函数库设置问题
  3. matlab仿真环境,高低温环境模拟系统MATLAB仿真研究
  4. python vbs库_Python语言之requests库
  5. 手把手教你如何下载大厂页面的字体——开发
  6. 数据库连接池优化配置(druid,dbcp,c3p0)
  7. net core框架介绍
  8. vue调试工具 -- vue-devtools 安装方法
  9. 在Tomcat中通过JOTM支持JTA
  10. 三星android智能手机usb驱动程序,三星手机驱动官方下载
  11. Office Open XML 文档格式(转)
  12. SQL Server维护计划自动备份数据库
  13. cortex-M3/M4 指令集
  14. 《自控力》第七章读书笔记
  15. 关于jupyter notebook闪退问题【我真真的够了,大家以后不要乱捣鼓电脑了,绝了】
  16. iOS-获取健康运动步数
  17. sql server(MsSql)字段命名,表命名,视图命名,SQL语句书写参考
  18. Alpha阶段敏捷冲刺③
  19. Dev C++下载及使用
  20. 绿联扩展坞拆解_拆解报告:绿联USB-C多功能拓展坞2A1C

热门文章

  1. PingingLab传世经典系列《CCNA完全配置宝典》-2.5 RIPv2基本配置
  2. 黄聪:php实现上传图片和等比例缩略图压缩图片
  3. Opera浏览器无法观看土豆 优酷 新浪视频的解决办法!
  4. Silverlight 2.0 RTW 正式版发布(附下载地址)!
  5. Spark RPC框架源码分析(二)RPC运行时序
  6. Github学习系列之Github是什么?
  7. java 子类重写父类的方法应注意的问题
  8. Jquery zTree实例
  9. Windows,Xampp,Zend Stadio搭建php运行环境
  10. SpringBoot介绍