iOS网络-04-大文件下载

大文件下载注意事项


  • 若不对下载的文件进行转存,会造成内存消耗急剧升高,甚至耗尽内存资源,造成程序终止。
  • 在文件下载过程中通常会出现中途停止的状况,若不做处理,就要重新开始下载,浪费流量。

大文件下载的解决方案


  • 对下载文件进行处理,每下载一点数据,就将数据写到磁盘中(通常是沙盒中),避免在内存累积数据(NSURLConnection下载)

    • 使用NSFileHandle类实现写数据
    • 使用NSOutputStream类实现写数据
  • 当下载任务终止时,记录任务终止时的位置信息,以便下次开始继续下载

大文件下载(NSURLConnection)


  • 未支持断点下载
  • 使用NSURLConnection的代理方式下载文件
  • 在下载任务的不同阶段回调的代理方法中,完成转移下载文件,及记录终止位置的任务
  • 使用NSFileHandle类实现写数据的下载步骤(完整核心代码)
    • 设置相关成员属性
    /**所要下载文件的总长度*/
    @property (nonatomic, assign) NSInteger contentLength;
    /**已下载文件的总长度*/
    @property (nonatomic, assign) NSInteger currentLength
    /**文件句柄,用来实现文件存储*/
    @property (nonatomic, strong) NSFileHandle *handle;
    • 创建、发送请求
    // 1. 创建请求路径
    NSURL *url = [NSURL URLWithString:@"此处为URL字符串"];
    // 2. 将URL封装成请求
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    // 3. 通过NSURLConnection,并设置代理
    [NSURLConnection connectionWithRequest:request delegate:self];
    • 遵守代理协议NSURLConnectionDataDelegate,实现代理方法
    /**
    * 接收到服务器响应时调用的方法
    */
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response
    {
        //获取所要下载文件的总长度
        self.contentLength = [response.allHeaderFields[@"Content-Length"] integerValue];
        //拼接一个沙盒中的文件路径
        NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"minion_15.mp4"];
        //创建指定路径的文件
        [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
        //创建文件句柄
        self.handle = [NSFileHandle fileHandleForWritingAtPath:filePath];
    }
    /**
    * 接收到服务器的数据时调用的方法
    */
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        //定位到文件尾部,将服务器每次返回的文件数据都拼接到文件尾部
        [self.handle seekToEndOfFile];
        //通过文件句柄,将文件写入到沙盒中
        [self.handle writeData:data];
        //拼接已下载文件总长度
        self.currentLength += data.length;
        //计算下载进度
        CGFloat progress = 1.0 * self.currentLength / self.contentLength;
    }
    /**
    * 文件下载完毕时调用的方法
    */
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        //关闭文件句柄,并清除
        [self.handle closeFile];
        self.handle = nil;
        //清空已下载文件长度
        self.currentLength = 0;
    }
  • 使用NSOutputStream类实现写数据的下载步骤(部分代码,其他部分代码同上
    • 设置NSOutputStream成员属性
    @property (nonatomic, strong) NSOutputStream *stream;
    • 初始化NSOutputStream对象,打开输出流
    /**接收到服务器响应的时候调用*/
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
        //获取下载数据保存的路径
        NSString *cache = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        NSString *filePath = [cache stringByAppendingPathComponent:response.suggestedFilename];
        //利用NSOutputStream往filePath文件中写数据,若append参数为yes,则会写到文件尾部
        self.stream = [[NSOutputStream alloc] initToFileAtPath:filePath append:YES];
        //打开数据流
        [self.stream open];
    }
    • 写文件数据
    /**接收到数据的时候调用*/
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        [self.stream write:[data bytes] maxLength:data.length];
    }
    • 关闭输出流
    /**数据下载完毕的时候调用*/
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        [self.stream close];
    }

大文件下载(NSURLSession)


  • 支持断点下载,自动记录停止下载时断点的位置
  • 遵守NSURLSessionDownloadDelegate协议
  • 使用NSURLSession下载大文件,被下载文件会被自动写入沙盒的临时文件夹tmp中
  • 下载完毕,通常需要将已下载文件移动其他位置(tmp文件夹中的数据被定时删除),通常是cache文件夹中
  • 详细的下载步骤
    • 设置下载任务task的为成员变量
    @property (nonatomic, strong) NSURLSessionDownloadTask *task;
    • 获取NSURLSession对象
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
    • 初始化下载任务任务
    self.task = [session downloadTaskWithURL:(此处为下载文件路径URL)];
    • 实现代理方法
    /**每当写入数据到临时文件的时候,就会调用一次该方法,通常在该方法中获取下载进度*/
    - (void)URLSession:(NSURLSession *)session downloadTask: (NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    {
        // 计算下载进度
        CGFloat progress = 1.0 * totalBytesWritten / totalBytesExpectedToWrite;
    }
    
    /**任务终止时调用的方法,通常用于断点下载*/
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
    {
        //fileOffset:下载任务中止时的偏移量
    }
    
    /**遇到错误的时候调用,error参数只能传递客户端的错误*/
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    { }
    
    /**下载完成的时候调用,需要将文件剪切到可以长期保存的文件夹中*/
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
    {
        //生成文件长期保存的路径
        NSString *file = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
        //获取文件句柄
        NSFileManager *fileManager = [NSFileManager defaultManager];
        //通过文件句柄,将文件剪切到文件长期保存的路径
        [fileManager moveItemAtURL:location toURL:[NSURL fileURLWithPath:file] error:nil];
    }
    • 操作任务状态
    /**开始/继续下载任务*/
    [self.task resume];
    
    /**暂停下载任务*/
    [self.task suspend];

本博客的最新状态将会同步到新浪微博账号:世俗孤岛

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 12:52:41

iOS网络-04-大文件下载的相关文章

IOS NSURLConnection(大文件下载)

一.大文件下载 1.方案:利用NSURLConnection和它的代理方法1> 发送一个请求// 1.URLNSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/videos.zip"];// 2.请求NSURLRequest *request = [NSURLRequest requestWithURL:url];// 3.下载(创建完conn对象后,会自动发起一个异步请求)[N

iOS网络-NSURLSessionDataTask大文件离线断点下载

什么叫离线断点下载,就是用户下载中关闭程序重新打开可以继续下载 代码实现如下: #import "ViewController.h" @interface ViewController ()<NSURLSessionDataDelegate> //输出流 @property (nonatomic, strong) NSOutputStream *stream ; //Task对象 @property (nonatomic, strong) NSURLSessionDataT

ios开发网络学习三:NSURLConnection小文件大文件下载

一:小文件下载 #import "ViewController.h" @interface ViewController ()<NSURLConnectionDataDelegate> /** 注释 */ @property (nonatomic, strong) NSMutableData *fileData; @property (nonatomic, assign) NSInteger totalSize; @property (weak, nonatomic) IB

【iOS开发-网络】关于大文件下载

大文件下载要使用NSURLConnection的代理方法 首先创建好url发出请求 //创建url NSURL *url = [NSURL URLWithString:@"http://localhost:8080/TFServer/resources/videos/minion_01.mp4"]; //创建请求 NSURLRequest *request = [NSURLRequest requestWithURL:url]; //发出一个异步请求 [NSURLConnection

iOS开发网络请求——大文件的多线程断点下载

iOS开发中网络请求技术已经是移动app必备技术,而网络中文件传输就是其中重点了.网络文件传输对移动客户端而言主要分为文件的上传和下载.作为开发者从技术角度会将文件分为小文件和大文件.小文件因为文件大小比较小导致传输所需时间少传输就快,因此不太容易影响用户体验,可用的技术就多.而大文件因为文件大小比较大导致传输时间长,因此就需要考虑到各种用户体验,比如避免在上传下载文件过程中阻塞主线程影响用户体验,就需要使用到多线程技术:为了给用户友好的进度提示,因此又需要开发中跟踪数据上传和下载数据的变化:为

网络编程---(数据请求+slider)将网络上的大文件下载到本地,并打印其进度

网络编程---将网络上的大文件下载到本地,并打印其进度. 点击"开始传输"按钮,将网络上的大文件先下载下来,下载完成后,保存到本地. UI效果图如下:            具体代码如下: //  ViewController.m //  0611---数据请求+滚动条 #import "ViewController.h" unsigned long tempLength; @interface ViewController () <NSURLConnecti

网络编程练习 -- 大文件下载

LWTViewController.m // // LWTViewController.m // 网络编程练习 -- 大文件下载 // // Created by apple on 14-6-28. // Copyright (c) 2014年 lwt. All rights reserved. // #import "LWTViewController.h" #import "LWTFileDownloadTool.h" @interface LWTViewCon

iOS网络-文件下载,断点下载,输出流下载

小文件下载 NSURLConnection-delegate实现,可以监听到下载的进度,但是还是无法解决内存飙升的问题,所以仅限小文件下载 1 @interface ViewController ()<NSURLConnectionDataDelegate> 2 @property (weak, nonatomic) IBOutlet UIProgressView *progressView; 3 /** 接收数据的data */ 4 @property (nonatomic, strong)

iOS网络高级编程:iPhone和iPad的企业应用开发之错误处理

本章内容 ●    iOS应用中的网络错误源 ●    检测网络的可达性 ●    错误处理的经验法则 ●    处理网络错误的设计模式 到目前为止,我们所介绍的iPhone与其他系统的网络交互都是基于一切正常这个假设.本章将会放弃这个假设,并深入探究网络的真实世界.在真实世界中,事情是会出错的,有时可能是非常严重的错误:手机进入与离开网络.包丢掉或是延迟:网络基础设施出错:偶尔用户还会出错.如果一切正常,那么编写iOS应用就会简单不少,不过遗憾的是现实并非如此.本章将会探讨导致网络操作失败的几