iOS-文件断点续传
* 移动客户端在和服务器交互的时候,上传和下载使用十分广泛。
* 在我们下载文件的时候,我们在点击暂停的时候可以暂停下载,点击下载的时候可以继续下载,这个功能如何实现?
* 下载进度条如何显示?
先大概叙述一下断点下载的原理:
* 首先先判断要判断要下载的文件在本地沙盒中是否存在。
* 如果存在的话,要判断下载文件的长度。
* 假设文件长度是500,我们发起下载请求的时候应该从500开始。
* 点击暂停下载,应该将链接断掉。
* 再次点击下载的时候,根据下载文件长度,继续下载。
下面与代码结合起来叙述具体的实现:
* 假设我们要下载的文件在服务器的路径为:http://localhost:8080:down/xcode_6.dmg;
* 我们将要下载的文件方法本地沙盒中。文件命名为:xcode.dmg.
* 获取文件保存路径的代码:(折叠)
-(NSString *)getFilePath
{
NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[];
NSString *filePath = [documentsPath stringByAppendingPathComponent:@"xcode.dmg"];
return filePath;
}
下载文件保存路径
* 因为下载的文件比较大,我们需要采取异步请求网络。
* 异步请求网络常用的有四个代理方法。
* 发起网络请求下载。(下载起始点为上次暂停点,判断上次暂停位置方法是,获取文件属性,从属性中可以查看文件长度,请求点为该长度后面的内容)
* 假设向获取某个字节的内容,可以使用:
//bytes = 0-499 请求前500个字节的内容
//bytes = 500- 请求500字节之后的内容
//bytes = 500-1000 请求资源中某一范围的内容
//bytes = 0-1,499-500 请求多个范围之间的内容
* 进度条过去文件下载进度,可以使用已经下载的文件的字节数/文件的总字节数。
下面为具体的代码段,里面有详细的注释:
#import <UIKit/UIKit.h> @interface ViewController : UIViewController<NSURLConnectionDataDelegate>
{
//进度条变量,显示文件下载进度
IBOutlet UIProgressView *_progress;
//文件处理,将下载的文件写入本地沙盒
NSFileHandle *_fileHandle;
//url连接,点解暂停,取消连接,点击下载,开始下载
NSURLConnection *_connection;
//已经接收数据大小
long long _receiveSize;
//文件总共的大小
long long _totalSize;
} //下载按钮点击响应函数
- (IBAction)download:(id)sender;
//暂停按钮点击响应函数
- (IBAction)pause:(id)sender; @end
- (IBAction)download:(id)sender
{
//文件的路径
NSString *string = @"http://localhost:8080/down/xcode_6.dmg";
//文件的路径转化为url
NSURL *url = [NSURL URLWithString:string];
//创建可变请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//判断沙盒路径下有没有这个文件,YES表示这个文件已经下载,NO表示还没有下载
if ([[NSFileManager defaultManager] fileExistsAtPath:[self getFilePath]] == YES)
{ //根据文件的属性,获取之前下载数据量是多少
NSDictionary *fileDic = [[NSFileManager defaultManager]attributesOfItemAtPath:[self getFilePath] error:nil];
//文件的长度就是已经下载的数据量
_receiveSize = [fileDic[NSFileSize] longLongValue];
//设置Range,从Range之后的内容开始下载
//bytes = 0-499 请求前500个字节的内容
//bytes = 500- 请求500字节之后的内容
//bytes = 500-1000 请求资源中某一范围的内容
//bytes = 0-1,499-500 请求多个范围之间的内容
NSString *bytes = [NSString stringWithFormat:@"bytes=%lld-",_receiveSize];
[request setValue:bytes forHTTPHeaderField:@"Range"]; }
//发起异步请求,文件比较法,使用异步请求
_connection = [NSURLConnection connectionWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
//分析响应头
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
//获取响应头,是一个字典
NSDictionary *responseHeader = httpResponse.allHeaderFields;
//接收文件总的大小等于已经下载的数据量,加上为下载的数据量
_totalSize = _receiveSize + [responseHeader[@"Content-Length"] longLongValue];
//创建文件管理类
NSFileManager *fileManager = [NSFileManager defaultManager];
//沙盒中不存在要下载的文件,就创建该文件
if ([fileManager fileExistsAtPath:[self getFilePath]] == NO)
{
[fileManager createFileAtPath:[self getFilePath] contents:nil attributes:nil];
}
//根据路径写入文件
_fileHandle = [NSFileHandle fileHandleForWritingAtPath:[self getFilePath]];
} - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//文件比较大的话,需要多次写入,写入的话,需要将光标定位到结尾
[_fileHandle seekToEndOfFile];
//将数据写入到文件
[_fileHandle writeData:data];
//最新接收到数据的大小等于文件中已有的数据,加上刚刚下载的数据量
_receiveSize = _receiveSize + data.length;
//计算进度
float jundu = (float)_receiveSize / _totalSize;
//使用进度条来表示进度
_progress.progress = jundu;
} - (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//文件完成传输,关闭文件管理
[_fileHandle closeFile];
} - (IBAction)pause:(id)sender
{
//点击暂停,取消请求连接
[_connection cancel];
_connection = nil;
} -(NSString *)getFilePath
{
NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *filePath = [documentsPath stringByAppendingPathComponent:@"xcode.dmg"];
return filePath;
}
iOS-文件断点续传的更多相关文章
- iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载+使用输出流代替文件句柄
前言:本篇讲解,在前篇iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载的基础上,使用输出流代替文件句柄实现大文件断点续传. 在实际开发中,输入输出流用的比较少,但 ...
- iOS——文件操作NSFileManager (创建、删除,复制,粘贴)
iOS——文件操作NSFileManager (创建.删除,复制,粘贴) iOS的沙盒机制,应用只能访问自己应用目录下的文件.iOS不像android,没有SD卡概念,不能直接访问图像.视 ...
- IOS文件操作的两种方式:NSFileManager操作和流操作
1.常见的NSFileManager文件方法 -(NSData *)contentsAtPath:path //从一个文件读取数据 -(BOOL)createFileAtPath: path cont ...
- 文件断点续传原理与实现—— ESFramework 通信框架4.0 进阶(12)
在ESFramework通信框架 4.0 快速上手(13) -- 文件传送,如此简单一文的详细介绍和ESFramework通信框架 4.0 快速上手(14) -- 聊天系统Demo,增加文件传送功能( ...
- IOS 文件解析
import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java ...
- iOS文件处理类
iOS文件处理类 这是一个用来简化iOS中关于文件操作的一个类,所有方法都为类方法. Source File.h // // File.h // FileManager // // http://ho ...
- iOS文件上传文件URL错误Invalid parameter not satisfying: fileURL'
一:iOS文件上传提示URL错误 Invalid parameter not satisfying: fileURL' 二:解决方法: NSString *imagePath = [[NSBundle ...
- IOS 文件夹结构
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/MyGameZone/article/details/24494765 IOS文件夹结构 说明 这些仅 ...
- js -- fileData 实现文件断点续传
前端实现文件的断点续传 一.一些知识准备 断点续传,既然有断,那就应该有文件分割的过程,一段一段的传. 以前文件无法分割,但随着HTML5新特性的引入,类似普通字符串.数组的分割,我们可以可以使用sl ...
- php实现大文件断点续传下载实例
php实现大文件断点续传下载实例,看完你就知道超过100M以上的大文件如何断点传输了,这个功能还是比较经典实用的,毕竟大文件上传功能经常用得到. require_once('download.clas ...
随机推荐
- Ecshop首页购物车数量调取问题
在page_header.lbi中调用SQL: <?php $sql = 'SELECT SUM(goods_number) AS number' . ' FROM ' . $GLOBALS[' ...
- AutoWidthInput
import React from 'react'; import PropTypes from 'prop-types'; class AutoWidthInput extends React.Co ...
- mysq--索引模块
问题:为什么要 使用索引? --->快速查询数据,但是仅仅这么回答,就是不专业的!!! 应该要分为数据量少的时候,不适用索引,走全表扫描的话,查询速率也是很快的 数据量大的话,使用索引,查询速率 ...
- 删除sqlserver管理器登录信息缓存
在Windows10下测试有效: C:\Users\<user>\AppData\Roaming\Microsoft\Microsoft SQL Server\100\Tools\Shel ...
- Swift开发中 JSON对象/JSON字符串/Data的互转
本文将介绍Swift开发中常用的转换(JSON对象/JSON字符串/Data之间的互相转换) #pragma mark - JSON(对象)----->JSON字符串 1.原生方法 //JSON ...
- mariadb多源主从复制错误跳过.md
mysql 的主从错误跳过和mariadb的多源主从复制错误跳过操作不同,请注意: 更改会话的default_master_connection变量 STOP SLAVE 'slave_account ...
- Jenkins注意点
这里要填写 在 Linux 上 生成的 git 私钥 并且带上 前后 注释 ------start ----- ---end -------
- mysql的字符串连接符
以前用SQL Server 连接字符串是用“+”,现在数据库用mysql,写个累加两个字段值SQL语句居然不支持"+",郁闷了半天在网上查下,才知道mysql里的+是数字相加的操作 ...
- VUE2.0声明周期钩子:不同阶段不同钩子的开启
- Python属性描述符(二)
Python存取属性的方式特别不对等,通过实例读取属性时,通常返回的是实例中定义的属性,但如果实例未曾定义过该属性,就会获取类属性,而为实例的属性赋值时,通常会在实例中创建属性,而不会影响到类本身.这 ...