OC - 16.大文件下载

大文件下载注意事项


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

大文件下载的解决方案


  • 对下载文件进行处理,每下载一点数据,就将数据写到磁盘中(通常是沙盒中),避免在内存累积数据(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-08-05 11:10:55

OC - 16.大文件下载的相关文章

2016 - 1- 23 大文件下载

---恢复内容开始--- 一: 利用NSFileHandle对象实现大文件下载 1.要了解NSFileHandle的用法,注意下载完要关闭这个对象.还要记得每次写入之前将它的文件指针挪位! // // ViewController.m // 多值参数 // // Created by Mac on 16/1/23. // Copyright © 2016年 Mac. All rights reserved. // #define ZZFile [ [NSSearchPathForDirector

ASP.NET 大文件下载的实现思路及代码

文件下载是一个网站最基本的功能,ASP.NET网站的文件下载功能实现也很简单,但是如果遇到大文件的下载而不做特殊处理的话,那将会出现不可预料的后果.本文就基于ASP.NET提供大文件下载的实现思路及代码. 当我们的网站需要支持下载大文件时,如果不做控制可能会导致用户在访问下载页面时发生无响应,使得浏览器崩溃.可以参考如下代码来避免这个问题. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

IOS-网络(大文件下载)

一.不合理方式 1 // 2 // ViewController.m 3 // IOS_0131_大文件下载 4 // 5 // Created by ma c on 16/1/31. 6 // Copyright © 2016年 博文科技. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 11 @interface ViewController ()<NSURLConnectionDataDelegate&

036_python的大文件下载以及进度条展示

复习 1.黏包现象 粘包现象的成因: tcp协议的特点,面向流的,为了保证可靠传输,所以有很多优化的机制. 无边界 所有在连接建立的基础上传递的数据之间没有界限. 收发消息很有可能不完全相等. 缓存机制,导致没发过去的消息会在发送端缓存,没接收完的消息会在接收端缓存. 解决: 给应用层定制协议 解决方案一:只发送一条信息 先发送一个定长表示待发送数据长度的bytes,先接收一个固定长度 再发送要发送的数据,再按照长度接收数据. 解决方案二 :发送的多条信息 先发送一个定长表示待发送字典长度的by

大文件下载--断点续传--NSURLConnection

有了上一篇文章的铺垫直接上代码,下面是分析原理. // ViewController.m // 大文件下载 // Created by apple on 15/11/11. // Copyright © 2015年 LDSmallCat. All rights reserved. #import "ViewController.h" #import "DACircularProgressView.h"//进度条的第三方框架 @interface ViewContro

微信营销的16大法宝

微信营销该怎么运营,如何才能达到成功营销的目的,与大家分享微信营销的16大法宝.1.一切一切的导向都是为了导向用户.一切一切的营销都是为了抓住用户的心理.一切一切的产品都是为了用户需求而改变.如微博微信一般,一切一切的一切都是用户在掌控! 2.不管是微博,还是微信.这些营销成功的案例都只可以拿来参考,永远不可能复制,哪个专家告诉你,按照这些去做就能够成功的,一定是忽悠! 3.没有产品谈营销的要么是流氓,要么是混蛋要么是骗子! 4.疯狂转发互动不是微博营销! 5.卖是营销的开始,诱是创意的引导.喊

Django 大文件下载

django提供文件下载时,若果文件较小,解决办法是先将要传送的内容全生成在内存中,然后再一次性传入Response对象中: def simple_file_download(request): # do something... content = open("simplefile", "rb").read() return HttpResponse(content) 如果文件非常大时,最简单的办法就是使用静态文件服务器,比如Apache或者Nginx服务器来处理

NSURLConnection实现大文件下载

NSURLConnection实现大文件下载 1.方案:利用NSURLConnection和它的代理方法 1> 发送一个请求 // 1.URL NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/videos.zip"]; // 2.请求 NSURLRequest *request = [NSURLRequest requestWithURL:url]; // 3.下载(创建完c

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