·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> app软件开发 >> IOS开发 >> iOS-文件断点续传

iOS-文件断点续传

作者:佚名      IOS开发编辑:admin      更新时间:2022-07-23

* 移动客户端在和服务器交互的时候,上传和下载使用十分广泛。

* 在我们下载文件的时候,我们在点击暂停的时候可以暂停下载,点击下载的时候可以继续下载,这个功能如何实现?

* 下载进度条如何显示?

先大概叙述一下断点下载的原理:

* 首先先判断要判断要下载的文件在本地沙盒中是否存在。

* 如果存在的话,要判断下载文件的长度。

* 假设文件长度是500,我们发起下载请求的时候应该从500开始。

* 点击暂停下载,应该将链接断掉。

* 再次点击下载的时候,根据下载文件长度,继续下载。

下面与代码结合起来叙述具体的实现:

* 假设我们要下载的文件在服务器的路径为:http://localhost:8080:down/xcode_6.dmg;

* 我们将要下载的文件方法本地沙盒中。文件命名为:xcode.dmg.

* 获取文件保存路径的代码:(折叠)

1 -(NSString *)getFilePath
2 {
3     NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
4     NSString *filePath = [documentsPath stringByAppendingPathComponent:@"xcode.dmg"];
5     return filePath;
6 }
下载文件保存路径

* 因为下载的文件比较大,我们需要采取异步请求网络。

* 异步请求网络常用的有四个代理方法。

* 发起网络请求下载。(下载起始点为上次暂停点,判断上次暂停位置方法是,获取文件属性,从属性中可以查看文件长度,请求点为该长度后面的内容)

* 假设向获取某个字节的内容,可以使用:

 

    //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;
}