iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载+使用输出流代替文件句柄

简介:

前言:本篇讲解,在前篇iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载的基础上,使用输出流代替文件句柄实现大文件断点续传。

   在实际开发中,输入输出流用的比较少,但是用起来也是很方便的。iOS开发用到的输入输出流和在Java中的输入输出流是几乎一样的,本质也是一个意思:将网络返回的数据当做流来处理。

   输入输出的理解:输入到哪里?输出到哪里?这个问题不难理解,输入输出是要站着服务器角度来思考的,下面用图来解释:

代码关键词:

   1、在接收到响应头的代理方法里创建输出流(根据上面的图,下载自然需要创建输出流NSOutputStream)。

   2、在接收数据的代理方法中写(write)数据,注意写入的是data字节(data.bytes)。

   3、最后在下载完毕的代理方法里关闭输出流。

用来做代码练习的API接口:

MP4小视频:http://120.25.226.186:32812/resources/videos/minion_01.mp4

完整的关键代码:

#import "ViewController.h"

@interface ViewController ()
@property (nonatomic ,assign)NSInteger totalSzie;
@property (nonatomic ,assign)NSInteger currentSzie;
@property (nonatomic, strong) NSString *fileName;
/** 文件的路径*/
@property (nonatomic ,strong) NSString *fullPath;
/** 请求对象*/
@property (nonatomic ,strong)NSURLConnection *connect;
/** 输出流*/
@property (nonatomic ,strong)NSOutputStream *stream;
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@end

@implementation ViewController
#pragma mark ----------------------
#pragma mark Events
- (IBAction)downloadBtnClick:(id)sender
{
 
// [[NSFileManager defaultManager] removeItemAtPath:self.fullPath error:nil];
 
 [self download];
}
- (IBAction)cancelBtnClick:(id)sender
{
 //取消网络请求
 [self.connect cancel];
}

#pragma mark ----------------------
#pragma mark Methods
-(void)download
{
 NSLog(@"------");
 //1.确定url
 NSURL *url =[NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
 
 //2.创建请求对象
 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
 
 //设置请求头信息,说明只需要请求该资源的一部分数据
 /*
 bytes=0-1000 表示下载0~1000的数据
 bytes=0- 表示从0开始下载直到下载完毕
 bytes=100- 表示从0开始下载直到下载完毕
 */
 NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentSzie];
 [request setValue:range forHTTPHeaderField:@"Range"];
 NSLog(@"%@",range);
 
 //3.发送异步请求
 self.connect = [NSURLConnection connectionWithRequest:request delegate:self];
}

#pragma mark ----------------------
#pragma mark NSURLConnectionDataDelegate
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
 NSLog(@"--didReceiveResponse-");
 
 //判断是否已经下载过了
 if (self.currentSzie >0) {
 return;
 }
 
 //0.获得文件的总大小
 //expectedContentLength是本次请求的数据的大小,并不是整个
 self.totalSzie = response.expectedContentLength;
 
 //1.得到文件的名称
 self.fileName = response.suggestedFilename;
 
 //2.获得文件的全路径
 //caches
 NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
 
 NSString *fullPath = [caches stringByAppendingPathComponent:self.fileName];
 self.fullPath = fullPath;
 
 //3.创建输出流
 /*
 第一个参数: 写入数据的地址
 第二个参数: 表示要不要追加 断点续传肯定要追加
 */
 NSOutputStream *stream = [[NSOutputStream alloc]initToFileAtPath:fullPath append:YES];
 self.stream = stream;
 
 //4.打开数据流
 // 如果文件不存在,那么会自动创建一个空的文件
 [self.stream open];
}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
 //写数据
 /*
 第一个参数:要写的数据
 第二个参数:数据的长度
 */
 [self.stream write:data.bytes maxLength:data.length];
 
 
 //3.累加当前下载的数据大小
 self.currentSzie +=data.length;
 
 //4.计算文件的下载进度
 NSLog(@"%f",1.0 * self.currentSzie / self.totalSzie);
 
 self.progressView.progress = 1.0 * self.currentSzie / self.totalSzie;
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
 NSLog(@"%@",self.fullPath);
 
 //1.关闭输出流
 [self.stream close];
 
 //2.清空指针
 self.stream = nil;
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
}

@end

相关文章
|
11天前
|
前端开发 Android开发 iOS开发
【Flutter前端技术开发专栏】Flutter在Android与iOS上的性能对比
【4月更文挑战第30天】Flutter 框架实现跨平台移动应用,通过一致的 UI 渲染(Skia 引擎)、热重载功能和响应式框架提高开发效率和用户体验。然而,Android 和 iOS 的系统差异、渲染机制及编译过程影响性能。性能对比显示,iOS 可能因硬件优化提供更流畅体验,而 Android 更具灵活性和广泛硬件支持。开发者可采用代码、资源优化和特定平台优化策略,利用性能分析工具提升应用性能。
【Flutter前端技术开发专栏】Flutter在Android与iOS上的性能对比
|
11天前
|
机器学习/深度学习 安全 网络安全
数字堡垒的构筑者:网络安全与信息安全的深层剖析构建高效微服务架构:后端开发的新趋势
【4月更文挑战第30天】在信息技术高速发展的今天,构建坚不可摧的数字堡垒已成为个人、企业乃至国家安全的重要组成部分。本文深入探讨网络安全漏洞的本质、加密技术的进展以及提升安全意识的必要性,旨在为读者提供全面的网络安全与信息安全知识框架。通过对网络攻防技术的解析和案例研究,我们揭示了防御策略的关键点,并强调了持续教育在塑造安全文化中的作用。
|
11天前
|
存储 XML 前端开发
【Flutter前端技术开发专栏】Flutter中的网络请求与数据处理
【4月更文挑战第30天】本文介绍了Flutter开发中的网络请求和数据处理。 Flutter开发者可选择http(官方库)或dio(功能更强大)进行网络请求。http库简单易用,dio支持更多功能如拦截器。数据处理涉及JSON和XML解析,数据存储可选SharedPreferences或Hive,数据传递推荐使用InheritedWidget或Provider状态管理库。了解这些知识点能提升Flutter开发效率。
【Flutter前端技术开发专栏】Flutter中的网络请求与数据处理
|
11天前
|
存储 Swift iOS开发
使用Swift开发一个简单的iOS应用的详细步骤。
使用Swift开发iOS应用的步骤包括:创建Xcode项目,设计界面(Storyboard或代码),定义数据模型,实现业务逻辑,连接界面和逻辑,处理数据存储(如Core Data),添加网络请求(必要时),调试与测试,根据测试结果优化改进,最后提交至App Store或其它平台发布。
31 0
|
11天前
|
安全 Swift iOS开发
【Swift 开发专栏】Swift 与 UIKit:构建 iOS 应用界面
【4月更文挑战第30天】本文探讨了Swift和UIKit在构建iOS应用界面的关键技术和实践方法。Swift的简洁语法、类型安全和高效编程模型,加上与UIKit的紧密集成,使开发者能便捷地创建用户界面。UIKit提供视图、控制器、布局、动画和事件处理等功能,支持灵活的界面设计。实践中,遵循设计原则,合理组织视图层次,运用布局和动画,以及实现响应式设计,能提升界面质量和用户体验。文章通过登录、列表和详情界面的实际案例展示了Swift与UIKit的结合应用。
|
11天前
|
JSON 数据处理 Swift
【Swift 开发专栏】Swift 中的网络编程:URLSession 与 Alamofire
【4月更文挑战第30天】本文探讨了Swift中的网络编程,重点关注URLSession和Alamofire。URLSession是苹果提供的网络请求框架,允许底层控制和定制,适合需要高度灵活性的场景。Alamofire则是在URLSession基础上的第三方库,提供简洁接口和功能扩展,简化网络请求和错误处理。文中还介绍了两者在实际应用中的选择和使用场景,强调掌握网络编程基础的重要性。
|
11天前
|
存储 安全 Swift
【Swift 开发专栏】使用 Swift 开发一个简单的 iOS 应用
【4月更文挑战第30天】本文介绍了使用 Swift 开发简单 iOS 待办事项应用的步骤。首先,阐述了 iOS 开发的吸引力及 Swift 语言的优势。接着,详细说明了应用的需求和设计,包括添加、查看和删除待办事项的功能。开发步骤包括创建项目、界面搭建、数据存储、功能实现,并提供了相关代码示例。最后,强调了实际开发中需注意的细节和优化,旨在帮助初学者掌握 Swift 和 iOS 开发基础。
|
13天前
|
机器学习/深度学习 算法 TensorFlow
TensorFlow 2keras开发深度学习模型实例:多层感知器(MLP),卷积神经网络(CNN)和递归神经网络(RNN)
TensorFlow 2keras开发深度学习模型实例:多层感知器(MLP),卷积神经网络(CNN)和递归神经网络(RNN)
|
3天前
|
域名解析 网络协议 Linux
linux网络配置详解
linux网络配置详解
12 0
|
3天前
|
网络协议 Java Linux
【探索Linux】P.29(网络编程套接字 —— 简单的TCP网络程序模拟实现)
【探索Linux】P.29(网络编程套接字 —— 简单的TCP网络程序模拟实现)
10 0