当前位置: 首页 > 编程笔记 >

iOS开发实现下载器的基本功能(1)

贺奕
2023-03-14
本文向大家介绍iOS开发实现下载器的基本功能(1),包括了iOS开发实现下载器的基本功能(1)的使用技巧和注意事项,需要的朋友参考一下

今天,做了一个下载器的Demo,即从本地配置的Apache服务器上,下载指定的文件。这次,我们下载服务器根目录下的html.mp4文件。
按照惯例,我们先创建一个URL对象和请求。
 NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/html.mp4"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
这里有两点需要注意,第一,这个url的字符串是全英文的,如果在字符串中出现了中文,我们就不能直接调用URLWithString:这个方法,而是要先将url字符串存入一个字符串对象中,再将这个字符串通过 
[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
方法才可以,否则无法正常请求。 
由于是下载操作,我们就需要用到NSURLConnection的代理方法来实现,前提是先创建连接对象和对象的代理。 
//建立连接,立即执行
[NSURLConnection connectionWithRequest:request delegate:self]; 
 现在问题来了,代理不止一个可选,<NSURLConnectionDownloadDelegate>和<NSURLConnectionDataDelegate>,初次接触,本能地选择了第一个代理(因为从名字来看,第一个最像)。如果您的想法和我一样,那就错了,第一个代理中的方法实现后,确实可以获得数据,但是不知道数据存在了哪里,并不是我们指定的路径,您可以尝试一下。
 好,经过第一次的失败,我们选择第二个代理,进入头文件,我们看到了四个方法:

//获得响应
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
//获取数据
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
//断开连接
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
//发生错误
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error; 

我们可以清楚地了解每个方法的作用,您有兴趣可以打印下每个方法的参数瞧一瞧。
这里需要补充的是,我们加了几个属性

/// 文件下载流
@property (strong, nonatomic) NSOutputStream *fileStream;
/// 记录文件总长度
@property (assign, nonatomic) long long fileLength;
/// 文件当前长度
@property (assign, nonatomic) long long currentFileLength; 

关于NSOutputStream,还有一个NSFileHandle可以和他进行比较,只是后者会造成文件被重复追加。因此,我们选择前者。根据类名我们可以推断出应该还有一个NSInputStream,没错,一个下载流,一个上传流。 

第一步。在获得响应的方法中,我们从response参数里获得文件的总长度,并且置当前已经下载的文件长度是0,开启一个保存到指定路径的下载流,这里我们保存到桌面。

//获得响应
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
  self.fileLength = response.expectedContentLength;
  //当前文件长度置零
  self.currentFileLength = 0;
  self.fileStream = [[NSOutputStream alloc] initToFileAtPath:@"/Users/xxx/Desktop/html.mp4" append:YES];
  [self.fileStream open];
}

第二步。我们获得了数据,如果您在这个方法中打印数据,您就会发现当文件够大(几M就行)时,这个方法会被调用多次,也就是说,分多次获取数据。所以我们在这个方法中拼接数据,同时也要避免数据拼接后造成占用过多内存。我们累加已下载的数据的长度,计算已下载的百分比,并写入数据流中。在计算百分比时,记得转换类型哦,不然结果都是0,除了最后一个是1。

//获取数据
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//  NSLog(@"did receive:%@",data);
  self.currentFileLength += data.length;
  float progressPercent = (float)self.currentFileLength / self.fileLength;
  NSLog(@"have downloaded: %f", progressPercent);
  [self.fileStream write:data.bytes maxLength:data.length];
}

最后一步。实际上是两个方法,一个是下载完成调用,一个是下载失败调用。有一点需要注意,无论下载成功或失败,都需要把文件输出流关闭。

//断开连接
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
  NSLog(@"连接结束");
  [self.fileStream close];
}

//发生错误
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
  NSLog(@"%@",error);
  [self.fileStream close];
} 

这只是下载功能的基本实现,接下来会添加下载进度条,并对下载操作进行跟多优化(多线程,断点续传等),最后会对下载操作进行封装。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。

 类似资料:
  • 本文向大家介绍iOS开发中文件的上传和下载功能的基本实现,包括了iOS开发中文件的上传和下载功能的基本实现的使用技巧和注意事项,需要的朋友参考一下 文件的上传 说明:文件上传使用的时POST请求,通常把要上传的数据保存在请求体中。本文介绍如何不借助第三方框架实现iOS开发中得文件上传。   由于过程较为复杂,因此本文只贴出部分关键代码。 主控制器的关键代码: 补充说明: 文件上传请求数据格式 部分

  • 本文向大家介绍IOS开发实现录音功能,包括了IOS开发实现录音功能的使用技巧和注意事项,需要的朋友参考一下 导入框架: 声明全局变量: 在ViewDidLoad中: 按钮的触发事件 代理方法:

  • 本文向大家介绍iOS开发实现音频播放功能,包括了iOS开发实现音频播放功能的使用技巧和注意事项,需要的朋友参考一下 音频播放 1、介绍  - 功能介绍  用于播放比较长的音频、说明、音乐 ,使用到的是AVFoundation  - 框架介绍  * AVAudioPlayer  * 初始化:  注意 : (3)必须声明全局变量的音乐播放对象、或者是属性的音乐播放对象  才可以播放 (4)在退出播放页

  • 本文向大家介绍Zend Framework实现具有基本功能的留言本(附demo源码下载),包括了Zend Framework实现具有基本功能的留言本(附demo源码下载)的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Zend Framework实现具有基本功能的留言本。分享给大家供大家参考,具体如下: 一个留言本...具有的基本功能就是.1.发表留言. 2.回复留言.3.管理留言(修改,

  • 本文向大家介绍SpringMVC实现文件下载功能,包括了SpringMVC实现文件下载功能的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了SpringMVC文件下载的具体代码,供大家参考,具体内容如下 两个案例   1.为登录用户提供下载服务。   2.阻止仅通过输入网址即可获取下载。 文件下载概览   为了将文件发送给浏览器,我们需要在控制器中完成以下操作: 对请求处理方法使用vo

  • 本文向大家介绍iOS 三级下拉菜单功能实现,包括了iOS 三级下拉菜单功能实现的使用技巧和注意事项,需要的朋友参考一下 前言 App 常用控件 -- 多级下拉菜单, 如团购类, 房屋类, 对数据进行筛选. 有一级, 二级, 三级, 再多就不会以这种样式,呈现给用户了. 作者就简单聊一下 多级下拉菜单 一 目标 默认显示一个 TableView, 点击数据后, 添加第二个TableView, 并实现