iOS项目开发—文件下载功能的实现

一、简单说明

1.思路

把下载的data追加到文件的尾部,直到所有的数据下载完为止。

1.在连通了服务器的时候,创建一个空的文件到沙盒中NSFileManager(文件管理类)

2.创建写数据的文件句柄

3.在接收到服务器返回的数据后,把data写入到创建的空文件中,但是不能使用writeTofile(会覆盖)

3.1移动到文件的尾部

3.2从当前移动的位置,写入数据

4.服务器的数据加载完毕后关闭连接,不再输入数据在文件中

二、代码示例

1.代码:

新建一个类,让其继承自NSObject类,一个文件下载器只下载一个文件。

自定义类的TXFileDownloader.h代码:

 1 //
 2 //  TXFileDownloader.h
 3 //  文件下载
 4 //
 5 //  Created by 鑫 on 14/12/23.
 6 //  Copyright (c) 2014年 梁镋鑫. All rights reserved.
 7 //
 8
 9 #import <Foundation/Foundation.h>
10
11 @interface TXFileDownloader : NSObject
12 //下载的远程url(连接到服务器的路径)
13 @property(nonatomic,strong)NSString *url;
14 //下载后的存储路径(文件下载到什么地方)
15 @property(nonatomic,strong)NSString *destPath;
16 //是否正在下载(只有下载器内部清楚)
17 @property(nonatomic,readonly,getter = isDownloading)BOOL Downloading;
18 //用来监听下载进度
19 @property(nonatomic,copy)void (^progressHandler)(double progress);
20 //用来监听下载完成
21 @property(nonatomic,copy)void (^completionHandler)();
22 //用来监听下载错误
23 @property(nonatomic,copy)void(^failureHandler)(NSError *error);
24 -(void)pause;
25 -(void)start;
26 @end

自定义类的TXFileDownloader.m

  1 //  TXFileDownloader.m
  2 //  文件下载
  3 //
  4 //  Created by 鑫 on 14/12/23.
  5 //  Copyright (c) 2014年 梁镋鑫. All rights reserved.
  6 //
  7
  8 #import "TXFileDownloader.h"
  9 @interface TXFileDownloader ()<NSURLConnectionDataDelegate>
 10 //请求对象
 11 @property(nonatomic,strong)NSURLConnection *cnnt;
 12 //文件句柄
 13 @property(nonatomic,strong)NSFileHandle *writeHandle;
 14 //当前获取到的数据长度
 15 @property(nonatomic,assign)long long currentLength;
 16 //完整数据长度
 17 @property(nonatomic,assign)long long sumLength;
 18 @end
 19
 20 @implementation TXFileDownloader
 21 //开始下载
 22 -(void)start
 23 {
 24     _Downloading=YES;
 25
 26     //创建一个请求
 27     NSURL *URL=[NSURL URLWithString:self.url];
 28     NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:URL];
 29
 30     //设置请求头信息
 31     //self.currentLength字节部分重新开始读取
 32     NSString *value=[NSString stringWithFormat:@"bytes=%lld-",self.currentLength];
 33     [request setValue:value forHTTPHeaderField:@"Range"];
 34
 35     //发送请求(使用代理的方式)
 36     self.cnnt=[NSURLConnection connectionWithRequest:request delegate:self];
 37
 38 }
 39
 40 //暂停下载
 41 -(void)pause
 42 {
 43     _Downloading=NO;
 44     //取消发送请求
 45     [self.cnnt cancel];
 46     self.cnnt=nil;
 47 }
 48
 49 #pragma mark- NSURLConnectionDataDelegate代理方法
 50 /*
 51  *当接收到服务器的响应(连通了服务器)时会调用
 52  */
 53 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
 54 {
 55 #warning 判断是否是第一次连接
 56     if (self.sumLength) return;
 57
 58     //1.创建文件存数路径
 59     NSString *caches=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
 60     NSString *filePath=[caches stringByAppendingPathComponent:@"video.zip"];
 61
 62
 63
 64     //2.创建一个空的文件,到沙盒中
 65     NSFileManager *mgr=[NSFileManager defaultManager];
 66     //刚创建完毕的大小是o字节
 67     [mgr createFileAtPath:filePath contents:nil attributes:nil];
 68
 69     //3.创建写数据的文件句柄
 70     self.writeHandle=[NSFileHandle fileHandleForWritingAtPath:filePath];
 71
 72     //4.获取完整的文件长度
 73     self.sumLength=response.expectedContentLength;
 74 }
 75
 76 /*
 77  *当接收到服务器的数据时会调用(可能会被调用多次,每次只传递部分数据)
 78  */
 79 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
 80 {
 81     //累加接收到的数据长度
 82     self.currentLength+=data.length;
 83     //计算进度值
 84     double progress=(double)self.currentLength/self.sumLength;
 85     //    self.progress.progress=progress;
 86     if (self.progressHandler) {//传递进度值给block
 87         self.progressHandler(progress);
 88
 89         //相当于在此处调用了下面的代码
 90         //        ^(double progress)
 91         //        {
 92         //            //把进度的值,传递到控制器中进度条,以进行显示
 93         //            vc.progress.progress=progress;
 94         //        };
 95     }
 96
 97
 98     //一点一点接收数据。
 99     NSLog(@"接收到服务器的数据!---%d",data.length);
100     //把data写入到创建的空文件中,但是不能使用writeTofile(会覆盖)
101     //移动到文件的尾部
102     [self.writeHandle seekToEndOfFile];
103     //从当前移动的位置,写入数据
104     [self.writeHandle writeData:data];
105 }
106
107 /*
108  *当服务器的数据加载完毕时就会调用
109  */
110 -(void)connectionDidFinishLoading:(NSURLConnection *)connection
111 {
112     NSLog(@"下载完毕----%lld",self.sumLength);
113     //关闭连接,不再输入数据在文件中
114     [self.writeHandle closeFile];
115     self.writeHandle=nil;
116
117     //清空进度值
118     self.currentLength=0;
119     self.sumLength=0;
120
121     if (self.completionHandler) {//下载完成通知控制器
122         self.completionHandler();
123         //相当于下面的代码
124         //        ^{
125         //            NSLog(@"下载完成");
126         //            [self.btn setTitle:@"下载已经完成" forState:UIControlStateNormal];
127         //        }
128     }
129
130 }
131 /*
132  *请求错误(失败)的时候调用(请求超时\断网\没有网\,一般指客户端错误)
133  */
134 -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
135 {
136     if (self.failureHandler) {//通知控制器,下载出错
137         self.failureHandler(error);
138         //相当于调用了下面的代码
139         //        ^{
140         //            NSLog(@"下载错误!");
141         //        }
142     }
143 }
144
145 @end

实现代码:

主控制器TXViewController.m

 1 //
 2 //  TXViewController.m
 3 //  文件下载
 4 //
 5 //  Created by 鑫 on 14/12/23.
 6 //  Copyright (c) 2014年 梁镋鑫. All rights reserved.
 7 //
 8
 9 #import "TXViewController.h"
10 #import "TXFileDownloader.h"
11 @interface TXViewController ()
12
13
14 @property(nonatomic,strong)TXFileDownloader *fileDownloader;
15 @property (weak, nonatomic) IBOutlet UIButton *btn;
16 @property (weak, nonatomic) IBOutlet UIProgressView *progress;
17 @end
18
19 @implementation TXViewController
20
21 - (void)viewDidLoad
22 {
23     [super viewDidLoad];
24 }
25
26 #pragma mark-懒加载
27 -(TXFileDownloader *)fileDownloader
28 {
29     if (_fileDownloader==nil) {
30         _fileDownloader=[[TXFileDownloader alloc]init];
31         //设置文件下载路径
32         _fileDownloader.url=@"http://192.168.1.53:8080/MJServer/resources/video.zip";
33
34         //设置文件保存路径
35         NSString *caches=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
36         NSString *filePath=[caches stringByAppendingPathComponent:@"video.zip"];
37         _fileDownloader.destPath=filePath;
38
39         //获取10的真实类型,把它作为a的类型
40         //        typeof(10) a = 20; // int a = 20;
41         __weak typeof(self) vc=self;
42         _fileDownloader.progressHandler=^(double progress)
43         {
44             vc.progress.progress=progress;
45             NSLog(@"%f",progress);
46         };
47         _fileDownloader.completionHandler=^{
48             NSLog(@"下载完成");
49             [vc.btn setTitle:@"下载已经完成" forState:UIControlStateNormal];
50         };
51         _fileDownloader.failureHandler=^(NSError *error){
52             NSLog(@"下载错误!%@",error);
53         };
54     }
55     return _fileDownloader;
56 }
57
58 //点击下载按钮,处理操作
59 - (IBAction)star {
60     if (self.fileDownloader.isDownloading) {//如果正在下载,那么调用方法暂停
61         [self.fileDownloader pause];
62         [self.btn setTitle:@"暂停" forState:UIControlStateNormal];
63     }else//如果没有正在下载,那么调用下载方法
64     {
65         [self.fileDownloader start];
66         [self.btn setTitle:@"下载" forState:UIControlStateNormal];
67     }
68 }
69
70 @end

代码:

 

控制器想监听下载器的下载进度,控制器想监听下载器的下载完毕,控制器想监听下载器的下载失败等都可以使用block的方式进行。

打印查看:

2.代码说明

(1)创建文件存储路径(写入到沙盒)

NSString *caches=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

NSString *filePath=[caches stringByAppendingPathComponent:@"video.zip"];

(2)创建一个空的文件夹( NSFileManager类的使用)

NSFileManager *mgr=[NSFileManager defaultManager];

(3)创建写数据的文件句柄

self.writeHandle=[NSFileHandle fileHandleForWritingAtPath:filePath];

(4)把data写入到创建的空文件中,但是不能使用writeTofile(会覆盖)

移动句柄到文件的尾部     [self.writeHandle seekToEndOfFile];

(5)下载完毕的时候,关闭连接

[self.writeHandle closeFile];

3、Range简单说明

通过设置请求头Range可以指定每次从网路下载数据包的大小

Range示例

bytes=0-499 从0到499的头500个字节

bytes=500-999 从500到999的第二个500字节

bytes=500- 从500字节以后的所有字节

bytes=-500 最后500个字节

bytes=500-599,800-899 同时指定几个范围

Range小结

- 用于分隔

前面的数字表示起始字节数

后面的数组表示截止字节数,没有表示到末尾

, 用于分组,可以一次指定多个Range,不过很少用

注意:关键代码

从self.currentLength字节部分重新开始读取

NSString *value=[NSString stringWithFormat:@"bytes=%lld-",self.currentLength];

[request setValue:value forHTTPHeaderField:@"Range"];

时间: 2024-10-28 15:04:00

iOS项目开发—文件下载功能的实现的相关文章

ios项目开发(天气预报项目):使用正则获取 weather.com.cn网站信息

[objc] view plaincopyprint?在CODE上查看代码片派生到我的代码片 <pre code_snippet_id="346208" snippet_file_name="blog_20140515_1_2220869" name="code" class="cpp">- (NSString *)hmacsha1:(NSString *)text key:(NSString *)secret {

ios项目开发(天气预报项目):通过经纬度获取当前城市名称

 1 . 在项目里添加 CoreLocation.framework 2 .在 .h 文件输入如下: 1.#import <CoreLocation/CLLocation.h> 2.#import <CoreLocation/CLLocationManager.h> 3.#import <coreLocation/CLGeocoder.h> 4.#import <coreLocation/CLPlacemark.h> 3 . 在 .m文件输入如下: 1.

ios项目开发(天气预报项目):

本项目基于 <使用storyboards建立 Navigation Controller and Table View> http://uliweb.cpython.org/tutorial/view_chapter/424 创建, 代码中使用了 静态的 tableviewcell 增加了 textview,url,json数据解析 部分代码片段: // // cityViewController.h // weather1 // // Created by HeJiasheng on 13-

iOS项目开发实战——storyboard设置界面技巧与注意事项

在iOS开发中,使用Main.storyboard来设计界面是每一个iOS开发人员需要面对的问题,使用storyboard相比较Android中使用XML来设置布局,有优点也有缺陷,现在我们来谈谈storyboard的设计技巧. (1)直接使用鼠标右键可以直接缩放storyboard的缩放比例.当然你也可以用触摸板使用2根手指缩放. . (2)拖拽控件绑定到代码中,不一定要从设计界面的控件中进行拖拽,也可以直接从左侧的列表中拖拽,这样会更加清晰方便. . (3)如何添加修改超过一屏的控件.我们把

iOS项目开发实战——获取网页源代码的二进制数据

我在上一篇博客<iOS项目开发实战--iOS网络编程获取网页Html源代码>中讲述了如何获取一个网页的HTML源代码,可以满足一定的需求.但是由于特殊原因,我们想获取的是一个网页的二进制数据,那么应该怎么办呢? 具体实现如下: (1)创建一个iOS项目,Language选择Swift,然后在ViewController.swift 中写入如下代码: override func viewDidLoad() { super.viewDidLoad() var data = NSData(conte

iOS项目开发实战——设置视图的透明度改变动画

在iOS中 ,透明度的改变可以让View视图以一种渐变的效果动态的出现或者消退,非常有意思.这里我们将会对一个View控件的色块执行透明度改变的动画.关于其他的动画效果可以参考我的其他几篇博客<iOS项目开发实战--制作视图的平移动画以及解决移动异常问题>,<iOS项目开发实战--多个视图的平移动画与闭包函数的声明与调用>. (1)在Main.storyboard中拖入一个View,并且绑定到代码中. (2)实现代码如下: import UIKit class OpacityVie

iOS项目开发实战——学会使用TableView列表控件(四)plist读取与Section显示

文本将会实现把数据存储到plist文件里.然后在程序中进行读取.在TableView控件中依据不同的类别显示Section. 有关TableView 的其它实现,请參考<iOS项目开发实战--学会使用TableView列表控件(一)><iOS项目开发实战--学会使用TableView列表控件(二)><iOS项目开发实战--学会使用TableView列表控件(三)了解Section>. (1)新建一个Property List文件,这个也就是plist文件.我取名为dat

ios项目开发(webview初步):

1 . 建立一个 single view class 2 . 在view controller上建立3个控件 text view,button, webview 3 . 将 text view , webview风别命名为 url,web // // ViewController.h // webview1 // // Created by HeJiasheng on 13-11-12. // Copyright (c) 2013年 HeJiasheng. All rights reserved

ios项目开发(天气预报项目):hmacsha1 例子

- (NSString *)hmacsha1:(NSString *)text key:(NSString *)secret { NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding]; NSData *clearTextData = [text dataUsingEncoding:NSUTF8StringEncoding]; unsigned char result[20]; CCHmac(kCCHmacAlgS