小文件下载

NSURLConnection下载小文件

#import "ViewController.h"

@interface ViewController ()<NSURLConnectionDataDelegate>
/** 记录文件的总大小 */
@property (nonatomic, assign) long long totalSize;
/** 下载的文件名 */
@property (nonatomic, strong) NSString *fileName;
/** 已经下载的data */
@property (nonatomic, strong) NSMutableData *downLoadData;
@end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_04.mp4"];
NSURLRequest *rquest = [NSURLRequest requestWithURL:url];
// 发送请求
[NSURLConnection connectionWithRequest:rquest delegate:self]; } #pragma mark - NSURLConnectionDataDelegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *httpRespone = (NSHTTPURLResponse *)response;
_totalSize = httpRespone.expectedContentLength; // 获取下载文件的总大小
_fileName = httpRespone.suggestedFilename; // 下载文件的名
NSLog(@"%@", httpRespone);
// 获取响应头字段的value
// NSString *contentLength = httpRespone.allHeaderFields[@"Content-Length"]; // 也可以获取文件的总长度
} - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// 拼接NSData
[self.downLoadData appendData:data]; // 计算进度
NSUInteger currLength = self.downLoadData.length;
double progress = (currLength * 1.0 / self.totalSize) * 100;
NSLog(@"------------------%@", [NSString stringWithFormat:@"%.2f%%", progress]);
} - (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// 下载完成将下载的Data写入沙河
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
NSString *filePath = [path stringByAppendingPathComponent:self.fileName];
[self.downLoadData writeToFile:filePath options:kNilOptions error:nil]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{ } @end

NSURLSession下载小文件

- (void)viewDidLoad {
[super viewDidLoad]; NSURL *url = [NSURL URLWithString:@"http://img.zcool.cn/community/0142135541fe180000019ae9b8cf86.jpg@1280w_1l_2o_100sh.png"];
// 创建session
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSString *filePath = [FMFILE stringByAppendingPathComponent:response.suggestedFilename];
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil];
}]; // 执行task
[task resume]; }

NSURLSessionDownloadTask下载完文件后自动将文件临时存储在沙盒的tmp目录下,通过Block的location返回。我们需要将tmp目录下的文件剪切到要存储的目录下否则系统自动清理。

这里注意:[NSURL fileURLWithPath:filePath]返回的URL是带有协议头的,而[NSURL URLWithString:@""];返回的是不带协议头的URL。

因此开发中建议使用NSURLSessionDownloadTask下载小文件。

大文件下载

NSURLConnection下载大文件

大文件的下载不能像小文件下载的方式将服务器每次返回的data拼接到内存。而是需要边下载边写进沙盒,这里需要使用NSFileHander这个类。

#import "ViewController.h"

#define FMFILE NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject

@interface ViewController ()<NSURLConnectionDataDelegate>
/** 记录文件的总大小 */
@property (nonatomic, assign) long long totalLength;
/** 当前总长度 */
@property (nonatomic, assign) long long currLength; @property (nonatomic, strong) NSFileHandle *handle;
@end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_04.mp4"];
NSURLRequest *rquest = [NSURLRequest requestWithURL:url];
// 发送请求
[NSURLConnection connectionWithRequest:rquest delegate:self]; } #pragma mark - NSURLConnectionDataDelegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// 下载完成将下载的Data写入沙河
NSHTTPURLResponse *httpRespone = (NSHTTPURLResponse *)response;
NSString *fileName = httpRespone.suggestedFilename; // 下载文件的名
NSString *filePath = [FMFILE stringByAppendingPathComponent:fileName]; // 接收到一个响应创建空的文件
[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]; self.totalLength = httpRespone.expectedContentLength; // 获取下载文件的总大小 self.handle = [NSFileHandle fileHandleForWritingAtPath:filePath];
} - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{ // 每次文件从文件内容尾部拼接
[self.handle seekToEndOfFile]; // 开始写入数据
[self.handle writeData:data]; // 拼接总长度
self.currLength += data.length; // 计算当前进度
CGFloat progress = self.currLength * 1.0 / self.totalLength;
NSLog(@"下载进度----%.2f%%", progress *100); } - (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[self.handle closeFile];
self.handle = nil; // 清零数据
self.currLength = 0;
self.totalLength = 0;
} @end

NSURLSession下载大文件

#import "ViewController.h"

#define FMFILE NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject
@interface ViewController ()<NSURLSessionDownloadDelegate> @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_04.mp4"]; NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url]; [task resume];
} #pragma mark - NSURLSessionDataDelegate
/*
每当写入数据到临时文件就会调用该方法
bytesWritten 这次写入数据的长度
totalBytesWritten 已经写入的文件长度
totalBytesExpectedToWrite 要下载文件的中长度
*/
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
CGFloat progress = totalBytesWritten * 1.0 / totalBytesExpectedToWrite;
NSLog(@"----------%.2f%%", progress*100);
} /*
恢复下载
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{ } // 现在完毕
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSString *filePath = [FMFILE stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
// 剪切文件
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil];
} // 完成跟失败都会来到这个代理方法
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"------------%s", __func__);
}
@end

NSURLSession断点下载大文件

NSURLSession创建的Task的的父类NSURLSessionTask有三个方法,因此它的子类都有这些方法。我们就可以利用这几个方法做断点下载。

- (void)suspend;
- (void)resume;
- (void)cancel;

iOS开发系列-文件下载的更多相关文章

  1. iOS开发系列--网络开发

    概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微博.微信等,这些应用本身可能采用iOS开发,但是所有的数据支撑都是基于后台网络服务器的.如今,网络编程越来越普遍,孤立的应用通常是没有生命力 ...

  2. iOS开发系列--Swift语言

    概述 Swift是苹果2014年推出的全新的编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题.Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在 ...

  3. iOS开发系列文章(持续更新……)

    iOS开发系列的文章,内容循序渐进,包含C语言.ObjC.iOS开发以及日后要写的游戏开发和Swift编程几部分内容.文章会持续更新,希望大家多多关注,如果文章对你有帮助请点赞支持,多谢! 为了方便大 ...

  4. iOS开发系列--App扩展开发

    概述 从iOS 8 开始Apple引入了扩展(Extension)用于增强系统应用服务和应用之间的交互.它的出现让自定义键盘.系统分享集成等这些依靠系统服务的开发变成了可能.WWDC 2016上众多更 ...

  5. iOS开发系列--Swift进阶

    概述 上一篇文章<iOS开发系列--Swift语言>中对Swift的语法特点以及它和C.ObjC等其他语言的用法区别进行了介绍.当然,这只是Swift的入门基础,但是仅仅了解这些对于使用S ...

  6. iOS开发系列--通知与消息机制

    概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是本地 ...

  7. iOS开发系列--数据存取

    概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储到数据库.例如前面IOS开发系列-Objective-C之Foundation框架的文章中提到归档.plist文件存储, ...

  8. iOS开发系列--C语言之基础知识

    概览 当前移动开发的趋势已经势不可挡,这个系列希望浅谈一下个人对IOS开发的一些见解,这个IOS系列计划从几个角度去说IOS开发: C语言 OC基础 IOS开发(iphone/ipad) Swift ...

  9. iOS开发系列--让你的应用“动”起来

    --iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建 ...

随机推荐

  1. thinkphp 模块部署

    3.2对模块的访问是自动判断的,所以通常情况下无需配置模块列表即可访问,在部署模块的时候,默认情况下都是基于类似于子目录的URL方式来访问模块的,例如: http://serverName/Home/ ...

  2. Delphi如何实现无边框窗体的移动

    在控件的MouseDown事件中加入if (ssleft in Shift) then begin ReleaseCapture; Perform(WM_syscommand, $F012, 0);e ...

  3. NX二次开发-UFUN特征找xxx UF_MODL_ask_feat_xxx等函数(待补充)

    NX9+VS2012 #include <uf.h> #include <uf_modl.h> #include <uf_obj.h> #include <u ...

  4. Android中滑屏实现----触摸滑屏以及Scroller类详解 .

    转:http://blog.csdn.net/qinjuning/article/details/7419207 知识点一:  关于scrollTo()和scrollBy()以及偏移坐标的设置/取值问 ...

  5. 漏洞验证系列--MongoDB未授权访问

    本系列文章旨在对于有一定网络安全基础的人员,在日常工作中扫描出来的各种漏洞,如何进行验证,以区分该漏洞是否存在或是扫描器误报.请勿应用非法途径. 本漏洞是由于MongoDB未设置访问权限,用户可以直接 ...

  6. MyBatis mappers元素标签及其属性、配置

    mappers:映射器,以最佳的方式是告诉 MyBatis 到哪里去找映射文件. <!-- 使用相对于类路径的资源引用,要满足一个条件:1.即映射文件只要放在类路径下,就可以根据相对路径找到,放 ...

  7. KNN 实战

    KNN算法很简单,大致的工作原理是:给定训练数据样本和标签,对于某测试的一个样本数据,选择距离其最近的k个训练样本,这k个训练样本中所属类别最多的类即为该测试样本的预测标签.简称kNN.通常k是不大于 ...

  8. 初探.Net Core API 网关Ocelot(一)

    一.介绍 Ocelot 是基于.NetCore实现的开源的API网关,支持IdentityServer认证.Ocelot具有路由.请求聚合.服务发现.认证.鉴权.限流熔断等功能,并内置了负载均衡器与S ...

  9. 生产环境Docker部署ELK跨区访问kafka不通问题的解决

    由于分布式系统的日志集中采集的需求非常强烈,我们组通过调研和实践搭建了一套基于Docker的日志收集系统Amethyst. 我们首先在测试环境搭建了一套基于Docker swarm集群的ELK分布式环 ...

  10. Flutter 类似viewDidAppear 的任务处理

    前言 在任务之中 ,有些实时任务比较重的需求,需要在类似 iOS viewDidAppear 里面执行数据请求任务,如:上一个页面返回pop 后执行网络请求任务.在flutter中如何实现呢?  目前 ...