网络文件下载(提供多种下载方式)

(1)使用 NSURLConnection 直接方式

(2)使用 NSURLConnection 代理方式

(3)使用 NSURLSession 直接方式

(4)使用 NSURLSession 代理方式

(5)使用 AFNetworking 方式

附加功能:

(1)使用 AFNetworking 中的 AFNetworkReachabilityManager 来检查网络情况:

  • AFNetworkReachabilityStatusReachableViaWiFi:Wi-Fi 网络下
  • AFNetworkReachabilityStatusReachableViaWWAN:2G/3G/4G 蜂窝移动网络下
  • AFNetworkReachabilityStatusNotReachable:未连接网络

(2)使用 AFNetworking 中的 AFNetworkActivityIndicatorManager 来启动网络活动指示器:

1 #import "AFNetworkActivityIndicatorManager.h"
2
3 //启动网络活动指示器;会根据网络交互情况,实时显示或隐藏网络活动指示器;他通过「通知与消息机制」来实现 [UIApplication sharedApplication].networkActivityIndicatorVisible 的控制
4 [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;

效果如下:

ViewController.h

1 #import <UIKit/UIKit.h>
2
3 @interface ViewController : UITableViewController
4 @property (copy, nonatomic) NSArray *arrSampleName;
5
6 - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName;
7
8 @end 

ViewController.m

 1 #import "ViewController.h"
 2 #import "NSURLConnectionViewController.h"
 3 #import "NSURLConnectionDelegateViewController.h"
 4 #import "NSURLSessionViewController.h"
 5 #import "NSURLSessionDelegateViewController.h"
 6 #import "AFNetworkingViewController.h"
 7
 8 @interface ViewController ()
 9 - (void)layoutUI;
10 @end
11
12 @implementation ViewController
13 - (void)viewDidLoad {
14     [super viewDidLoad];
15
16     [self layoutUI];
17 }
18
19 - (void)didReceiveMemoryWarning {
20     [super didReceiveMemoryWarning];
21     // Dispose of any resources that can be recreated.
22 }
23
24 - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName {
25     if (self = [super initWithStyle:UITableViewStyleGrouped]) {
26         self.navigationItem.title = @"多种方式实现文件下载功能";
27         self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:nil action:nil];
28
29         _arrSampleName = arrSampleName;
30     }
31     return self;
32 }
33
34 - (void)layoutUI {
35 }
36
37 #pragma mark - UITableViewController相关方法重写
38 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
39     return 0.1;
40 }
41
42 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
43     return 1;
44 }
45
46 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
47     return [_arrSampleName count];
48 }
49
50 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
51     static NSString *cellIdentifier = @"cell";
52     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
53     if (!cell) {
54         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
55     }
56     cell.textLabel.text = _arrSampleName[indexPath.row];
57     return cell;
58 }
59
60 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
61     switch (indexPath.row) {
62         case 0: {
63             NSURLConnectionViewController *connectionVC = [NSURLConnectionViewController new];
64             [self.navigationController pushViewController:connectionVC animated:YES];
65             break;
66         }
67         case 1: {
68             NSURLConnectionDelegateViewController *connectionDelegateVC = [NSURLConnectionDelegateViewController new];
69             [self.navigationController pushViewController:connectionDelegateVC animated:YES];
70             break;
71         }
72         case 2: {
73             NSURLSessionViewController *sessionVC = [NSURLSessionViewController new];
74             [self.navigationController pushViewController:sessionVC animated:YES];
75             break;
76         }
77         case 3: {
78             NSURLSessionDelegateViewController *sessionDelegateVC = [NSURLSessionDelegateViewController new];
79             [self.navigationController pushViewController:sessionDelegateVC animated:YES];
80             break;
81         }
82         case 4: {
83             AFNetworkingViewController *networkingVC = [AFNetworkingViewController new];
84             [self.navigationController pushViewController:networkingVC animated:YES];
85             break;
86         }
87         default:
88             break;
89     }
90 }
91
92 @end 

PrefixHeader.pch

1 #define kFileURLStr @"http://files.cnblogs.com/files/huangjianwu/metro_demo使用Highcharts实现图表展示.zip"
2
3 #define kTitleOfNSURLConnection @"使用 NSURLConnection 直接方式"
4 #define kTitleOfNSURLConnectionDelegate @"使用 NSURLConnection 代理方式"
5 #define kTitleOfNSURLSession @"使用 NSURLSession 直接方式"
6 #define kTitleOfNSURLSessionDelegate @"使用 NSURLSession 代理方式"
7 #define kTitleOfAFNetworking @"使用 AFNetworking 方式"
8
9 #define kApplication [UIApplication sharedApplication] 

UIButton+BeautifulButton.h

 1 #import <UIKit/UIKit.h>
 2
 3 @interface UIButton (BeautifulButton)
 4 /**
 5  *  根据按钮文字颜色,返回对应文字颜色的圆角按钮
 6  *
 7  *  @param tintColor 按钮文字颜色;nil 的话就为深灰色
 8  */
 9 - (void)beautifulButton:(UIColor *)tintColor;
10
11 @end 

UIButton+BeautifulButton.m

 1 #import "UIButton+BeautifulButton.h"
 2
 3 @implementation UIButton (BeautifulButton)
 4
 5 - (void)beautifulButton:(UIColor *)tintColor {
 6     self.tintColor = tintColor ?: [UIColor darkGrayColor];
 7     self.layer.masksToBounds = YES;
 8     self.layer.cornerRadius = 10.0;
 9     self.layer.borderColor = [UIColor grayColor].CGColor;
10     self.layer.borderWidth = 1.0;
11 }
12
13 @end 

NSURLConnectionViewController.h

1 #import <UIKit/UIKit.h>
2
3 @interface NSURLConnectionViewController : UIViewController
4 @property (strong, nonatomic) IBOutlet UILabel *lblFileName;
5 @property (strong, nonatomic) IBOutlet UILabel *lblMessage;
6 @property (strong, nonatomic) IBOutlet UIButton *btnDownloadFile;
7
8 @end 

NSURLConnectionViewController.m

 1 #import "NSURLConnectionViewController.h"
 2 #import "UIButton+BeautifulButton.h"
 3
 4 @interface NSURLConnectionViewController ()
 5 - (void)layoutUI;
 6 - (void)saveDataToDisk:(NSData *)data;
 7 @end
 8
 9 @implementation NSURLConnectionViewController
10
11 - (void)viewDidLoad {
12     [super viewDidLoad];
13
14     [self layoutUI];
15 }
16
17 - (void)didReceiveMemoryWarning {
18     [super didReceiveMemoryWarning];
19     // Dispose of any resources that can be recreated.
20 }
21
22 - (void)layoutUI {
23     self.navigationItem.title = kTitleOfNSURLConnection;
24     self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.000];
25
26     [_btnDownloadFile beautifulButton:nil];
27 }
28
29 - (void)saveDataToDisk:(NSData *)data {
30     //数据接收完保存文件;注意苹果官方要求:下载数据只能保存在缓存目录(/Library/Caches)
31     NSString *savePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
32     savePath = [savePath stringByAppendingPathComponent:_lblFileName.text];
33     [data writeToFile:savePath atomically:YES]; //writeToFile: 方法:如果 savePath 文件存在,他会执行覆盖
34 }
35
36 - (IBAction)downloadFile:(id)sender {
37     _lblMessage.text = @"下载中...";
38
39     NSString *fileURLStr = kFileURLStr;
40     //编码操作;对应的解码操作是用 stringByRemovingPercentEncoding 方法
41     fileURLStr = [fileURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
42     NSURL *fileURL = [NSURL URLWithString:fileURLStr];
43
44     //创建请求
45     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL];
46
47     //创建连接;Apple 提供的处理一般请求的两种方法,他们不需要进行一系列的 NSURLConnectionDataDelegate 委托协议方法操作,简洁直观
48     //方法一:发送一个同步请求;不建议使用,因为当前线程是主线程的话,会造成线程阻塞,一般比较少用
49 //    NSURLResponse *response;
50 //    NSError *connectionError;
51 //    NSData *data = [NSURLConnection sendSynchronousRequest:request
52 //                                         returningResponse:&response
53 //                                                     error:&connectionError];
54 //    if (!connectionError) {
55 //        [self saveDataToDisk:data];
56 //        NSLog(@"保存成功");
57 //
58 //        _lblMessage.text = @"下载完成";
59 //    } else {
60 //        NSLog(@"下载失败,错误信息:%@", connectionError.localizedDescription);
61 //
62 //        _lblMessage.text = @"下载失败";
63 //    }
64
65     //方法二:发送一个异步请求
66     [NSURLConnection sendAsynchronousRequest:request
67                                        queue:[NSOperationQueue mainQueue]
68                            completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
69                                if (!connectionError) {
70                                    [self saveDataToDisk:data];
71                                    NSLog(@"保存成功");
72
73                                    _lblMessage.text = @"下载完成";
74
75                                } else {
76                                    NSLog(@"下载失败,错误信息:%@", connectionError.localizedDescription);
77
78                                    _lblMessage.text = @"下载失败";
79                                }
80                            }];
81 }
82
83 @end 

NSURLConnectionViewController.xib

 

NSURLConnectionDelegateViewController.h

 1 #import <UIKit/UIKit.h>
 2
 3 @interface NSURLConnectionDelegateViewController : UIViewController
 4 @property (strong, nonatomic) NSMutableData *mDataReceive;
 5 @property (assign, nonatomic) NSUInteger totalDataLength;
 6
 7 @property (strong, nonatomic) IBOutlet UILabel *lblFileName;
 8 @property (strong, nonatomic) IBOutlet UIProgressView *progVDownloadFile;
 9 @property (strong, nonatomic) IBOutlet UILabel *lblMessage;
10 @property (strong, nonatomic) IBOutlet UIButton *btnDownloadFile;
11
12 @end 

NSURLConnectionDelegateViewController.m

  1 #import "NSURLConnectionDelegateViewController.h"
  2 #import "UIButton+BeautifulButton.h"
  3
  4 @interface NSURLConnectionDelegateViewController ()
  5 - (void)layoutUI;
  6 - (BOOL)isExistCacheInMemory:(NSURLRequest *)request;
  7 - (void)updateProgress;
  8 @end
  9
 10 @implementation NSURLConnectionDelegateViewController
 11
 12 - (void)viewDidLoad {
 13     [super viewDidLoad];
 14
 15     [self layoutUI];
 16 }
 17
 18 - (void)didReceiveMemoryWarning {
 19     [super didReceiveMemoryWarning];
 20     // Dispose of any resources that can be recreated.
 21 }
 22
 23 - (void)layoutUI {
 24     self.navigationItem.title = kTitleOfNSURLConnectionDelegate;
 25     self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.000];
 26
 27     [_btnDownloadFile beautifulButton:nil];
 28 }
 29
 30 - (BOOL)isExistCacheInMemory:(NSURLRequest *)request {
 31     BOOL isExistCache = NO;
 32     NSURLCache *cache = [NSURLCache sharedURLCache];
 33     [cache setMemoryCapacity:1024 * 1024]; //1M
 34
 35     NSCachedURLResponse *response = [cache cachedResponseForRequest:request];
 36     if (response != nil) {
 37         NSLog(@"内存中存在对应请求的响应缓存");
 38         isExistCache = YES;
 39     }
 40     return isExistCache;
 41 }
 42
 43 - (void)updateProgress {
 44     NSUInteger receiveDataLength = _mDataReceive.length;
 45     if (receiveDataLength == _totalDataLength) {
 46         _lblMessage.text = @"下载完成";
 47         kApplication.networkActivityIndicatorVisible = NO;
 48     } else {
 49         _lblMessage.text = @"下载中...";
 50         kApplication.networkActivityIndicatorVisible = YES;
 51         _progVDownloadFile.progress = (float)receiveDataLength / _totalDataLength;
 52     }
 53 }
 54
 55 - (IBAction)downloadFile:(id)sender {
 56     /*
 57      此例子更多的是希望大家了解代理方法接收响应数据的过程,实际开发中也不可能使用这种方法进行文件下载。这种下载有个致命的问题:无法进行大文件下载。因为代理方法在接收数据时虽然表面看起来是每次读取一部分响应数据,事实上它只有一次请求并且也只接收了一次服务器响应,只是当响应数据较大时系统会重复调用数据接收方法,每次将已读取的数据拿出一部分交给数据接收方法而已。在这个过程中其实早已经将响应数据全部拿到,只是分批交给开发者而已。这样一来对于几个G的文件如果进行下载,那么不用说是真机下载了,就算是模拟器恐怕也是不现实的。
 58      实际开发文件下载的时候不管是通过代理方法还是静态方法执行请求和响应,我们都会分批请求数据,而不是一次性请求数据。假设一个文件有1G,那么只要每次请求1M的数据,请求1024次也就下载完了。那么如何让服务器每次只返回1M的数据呢?
 59      在网络开发中可以在请求的头文件中设置一个Range信息,它代表请求数据的大小。通过这个字段配合服务器端可以精确的控制每次服务器响应的数据范围。例如指定bytes=0-1023,然后在服务器端解析Range信息,返回该文件的0到1023之间的数据的数据即可(共1024Byte)。这样,只要在每次发送请求控制这个头文件信息就可以做到分批请求。
 60      当然,为了让整个数据保持完整,每次请求的数据都需要逐步追加直到整个文件请求完成。但是如何知道整个文件的大小?其实在此例子通过头文件信息获取整个文件大小,他请求整个数据,这样做对分段下载就没有任何意义了。所幸在WEB开发中我们还有另一种请求方法“HEAD”,通过这种请求服务器只会响应头信息,其他数据不会返回给客户端,这样一来整个数据的大小也就可以得到了。
 61      */
 62
 63
 64     NSString *fileURLStr = kFileURLStr;
 65     //编码操作;对应的解码操作是用 stringByRemovingPercentEncoding 方法
 66     fileURLStr = [fileURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
 67     NSURL *fileURL = [NSURL URLWithString:fileURLStr];
 68
 69     /*创建请求
 70      cachePolicy:缓存策略
 71      1、NSURLRequestUseProtocolCachePolicy 协议缓存,根据 response 中的 Cache-Control 字段判断缓存是否有效,如果缓存有效则使用缓存数据否则重新从服务器请求
 72      2、NSURLRequestReloadIgnoringLocalCacheData 不使用缓存,直接请求新数据
 73      3、NSURLRequestReloadIgnoringCacheData 等同于 NSURLRequestReloadIgnoringLocalCacheData
 74      4、NSURLRequestReturnCacheDataElseLoad 直接使用缓存数据不管是否有效,没有缓存则重新请求
 75      5、NSURLRequestReturnCacheDataDontLoad 直接使用缓存数据不管是否有效,没有缓存数据则失败
 76
 77      timeoutInterval:超时时间设置(默认60s)
 78      */
 79     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:fileURL
 80                                                   cachePolicy:NSURLRequestUseProtocolCachePolicy
 81                                               timeoutInterval:60.0];
 82     if ([self isExistCacheInMemory:request]) {
 83         request = [[NSURLRequest alloc] initWithURL:fileURL
 84                                         cachePolicy:NSURLRequestReturnCacheDataDontLoad
 85                                     timeoutInterval:60.0];
 86     }
 87
 88     //创建连接,异步操作
 89     NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
 90                                                                   delegate:self];
 91     [connection start]; //启动连接
 92 }
 93
 94 #pragma mark - NSURLConnectionDataDelegate
 95 - (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response {
 96     NSLog(@"即将发送请求");
 97
 98     return request;
 99 }
100
101 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
102     NSLog(@"已经接收到响应");
103
104     _mDataReceive = [NSMutableData new];
105     _progVDownloadFile.progress = 0.0;
106
107     //通过响应头中的 Content-Length 获取到整个响应的总长度
108     /*
109      {
110      "Accept-Ranges" = bytes;
111      "Cache-Control" = "max-age=7776000";
112      "Content-Length" = 592441;
113      "Content-Type" = "application/x-zip-compressed";
114      Date = "Wed, 02 Sep 2015 13:17:01 GMT";
115      Etag = "\"d8f617371f9cd01:0\"";
116      "Last-Modified" = "Mon, 01 Jun 2015 03:58:27 GMT";
117      Server = "Microsoft-IIS/7.5";
118      "X-Powered-By" = "ASP.NET";
119      }
120      */
121     NSDictionary *dicHeaderField = [(NSHTTPURLResponse *)response allHeaderFields];
122     _totalDataLength = [[dicHeaderField objectForKey:@"Content-Length"] integerValue];
123 }
124
125 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
126     NSLog(@"已经接收到响应数据,数据长度为%lu字节...", (unsigned long)[data length]);
127
128     [_mDataReceive appendData:data]; //连续接收数据
129     [self updateProgress]; //连续更新进度条
130 }
131
132 - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
133     NSLog(@"已经接收完所有响应数据");
134
135     NSString *savePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
136     savePath = [savePath stringByAppendingPathComponent:_lblFileName.text];
137     [_mDataReceive writeToFile:savePath atomically:YES];
138 }
139
140 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
141     //如果连接超时或者连接地址错误可能就会报错
142     NSLog(@"连接错误,错误信息:%@", error.localizedDescription);
143
144     _lblMessage.text = @"连接错误";
145 }
146
147 @end

NSURLConnectionDelegateViewController.xib

 

NSURLSessionViewController.h

1 #import <UIKit/UIKit.h>
2
3 @interface NSURLSessionViewController : UIViewController
4 @property (strong, nonatomic) IBOutlet UILabel *lblFileName;
5 @property (strong, nonatomic) IBOutlet UILabel *lblMessage;
6 @property (strong, nonatomic) IBOutlet UIButton *btnDownloadFile;
7
8 @end 

NSURLSessionViewController.m

  1 #import "NSURLSessionViewController.h"
  2 #import "UIButton+BeautifulButton.h"
  3
  4 @interface NSURLSessionViewController ()
  5 - (void)layoutUI;
  6 @end
  7
  8 @implementation NSURLSessionViewController
  9
 10 - (void)viewDidLoad {
 11     [super viewDidLoad];
 12
 13     [self layoutUI];
 14 }
 15
 16 - (void)didReceiveMemoryWarning {
 17     [super didReceiveMemoryWarning];
 18     // Dispose of any resources that can be recreated.
 19 }
 20
 21 - (void)layoutUI {
 22     self.navigationItem.title = kTitleOfNSURLSession;
 23     self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.000];
 24
 25     [_btnDownloadFile beautifulButton:nil];
 26 }
 27
 28 - (IBAction)downloadFile:(id)sender {
 29     _lblMessage.text = @"下载中...";
 30
 31     NSString *fileURLStr = kFileURLStr;
 32     //编码操作;对应的解码操作是用 stringByRemovingPercentEncoding 方法
 33     fileURLStr = [fileURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
 34     NSURL *fileURL = [NSURL URLWithString:fileURLStr];
 35
 36     //创建请求
 37     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL];
 38
 39     //创建会话(这里使用了一个全局会话)
 40     NSURLSession *session = [NSURLSession sharedSession];
 41
 42     //创建下载任务,并且启动他;在非主线程中执行
 43     NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
 44         __block void (^updateUI)(); //声明用于主线程更新 UI 的代码块
 45
 46         if (!error) {
 47             NSLog(@"下载后的临时保存路径:%@", location);
 48
 49             NSString *savePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
 50             savePath = [savePath stringByAppendingPathComponent:_lblFileName.text];
 51             NSURL *saveURL = [NSURL fileURLWithPath:savePath];
 52             NSError *saveError;
 53             NSFileManager *fileManager = [NSFileManager defaultManager];
 54             //判断是否存在旧的目标文件,如果存在就先移除;避免无法复制问题
 55             if ([fileManager fileExistsAtPath:savePath]) {
 56                 [fileManager removeItemAtPath:savePath error:&saveError];
 57                 if (saveError) {
 58                     NSLog(@"移除旧的目标文件失败,错误信息:%@", saveError.localizedDescription);
 59
 60                     updateUI = ^ {
 61                         _lblMessage.text = @"下载失败";
 62                     };
 63                 }
 64             }
 65             if (!saveError) {
 66                 //把源文件复制到目标文件,当目标文件存在时,会抛出一个错误到 error 参数指向的对象实例
 67                 //方法一(path 不能有 file:// 前缀)
 68                 //                [fileManager copyItemAtPath:[location path]
 69                 //                                     toPath:savePath
 70                 //                                      error:&saveError];
 71
 72                 //方法二
 73                 [fileManager copyItemAtURL:location
 74                                      toURL:saveURL
 75                                      error:&saveError];
 76
 77                 if (!saveError) {
 78                     NSLog(@"保存成功");
 79
 80                     updateUI = ^ {
 81                         _lblMessage.text = @"下载完成";
 82                     };
 83                 } else {
 84                     NSLog(@"保存失败,错误信息:%@", saveError.localizedDescription);
 85
 86                     updateUI = ^ {
 87                         _lblMessage.text = @"下载失败";
 88                     };
 89                 }
 90             }
 91
 92         } else {
 93             NSLog(@"下载失败,错误信息:%@", error.localizedDescription);
 94
 95             updateUI = ^ {
 96                 _lblMessage.text = @"下载失败";
 97             };
 98         }
 99
100         dispatch_async(dispatch_get_main_queue(), updateUI); //使用主队列异步方式(主线程)执行更新 UI 的代码块
101     }];
102     [downloadTask resume]; //恢复线程,启动任务
103 }
104
105 @end 

NSURLSessionViewController.xib

 

NSURLSessionDelegateViewController.h

 1 #import <UIKit/UIKit.h>
 2
 3 @interface NSURLSessionDelegateViewController : UIViewController <NSURLSessionDownloadDelegate>
 4 @property (strong, nonatomic) NSURLSessionDownloadTask *downloadTask;
 5
 6 @property (strong, nonatomic) IBOutlet UILabel *lblFileName;
 7 @property (strong, nonatomic) IBOutlet UIProgressView *progVDownloadFile;
 8 @property (strong, nonatomic) IBOutlet UILabel *lblMessage;
 9 @property (strong, nonatomic) IBOutlet UIButton *btnDownloadFile;
10 @property (strong, nonatomic) IBOutlet UIButton *btnCancel;
11 @property (strong, nonatomic) IBOutlet UIButton *btnSuspend;
12 @property (strong, nonatomic) IBOutlet UIButton *btnResume;
13
14 @end 

NSURLSessionDelegateViewController.m

  1 #import "NSURLSessionDelegateViewController.h"
  2 #import "UIButton+BeautifulButton.h"
  3
  4 @interface NSURLSessionDelegateViewController ()
  5 - (void)layoutUI;
  6 - (NSURLSession *)defaultSession;
  7 - (NSURLSession *)backgroundSession;
  8 - (void)updateProgress:(int64_t)receiveDataLength totalDataLength:(int64_t)totalDataLength;
  9 @end
 10
 11 @implementation NSURLSessionDelegateViewController
 12
 13 - (void)viewDidLoad {
 14     [super viewDidLoad];
 15
 16     [self layoutUI];
 17 }
 18
 19 - (void)didReceiveMemoryWarning {
 20     [super didReceiveMemoryWarning];
 21     // Dispose of any resources that can be recreated.
 22 }
 23
 24 - (void)layoutUI {
 25     self.navigationItem.title = kTitleOfNSURLSessionDelegate;
 26     self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.000];
 27
 28     [_btnDownloadFile beautifulButton:nil];
 29     [_btnCancel beautifulButton:[UIColor redColor]];
 30     [_btnSuspend beautifulButton:[UIColor purpleColor]];
 31     [_btnResume beautifulButton:[UIColor orangeColor]];
 32 }
 33
 34 - (NSURLSession *)defaultSession {
 35     /*
 36      NSURLSession 支持进程三种会话:
 37      1、defaultSessionConfiguration:进程内会话(默认会话),用硬盘来缓存数据。
 38      2、ephemeralSessionConfiguration:临时的进程内会话(内存),不会将 cookie、缓存储存到本地,只会放到内存中,当应用程序退出后数据也会消失。
 39      3、backgroundSessionConfiguration:后台会话,相比默认会话,该会话会在后台开启一个线程进行网络数据处理。
 40      */
 41
 42     //创建会话配置「进程内会话」
 43     NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
 44     sessionConfiguration.timeoutIntervalForRequest = 60.0; //请求超时时间;默认为60秒
 45     sessionConfiguration.allowsCellularAccess = YES; //是否允许蜂窝网络访问(2G/3G/4G)
 46     sessionConfiguration.HTTPMaximumConnectionsPerHost = 4; //限制每次最多连接数;在 iOS 中默认值为4
 47
 48     //创建会话
 49     NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration
 50                                                           delegate:self
 51                                                      delegateQueue:nil];
 52     return session;
 53 }
 54
 55 - (NSURLSession *)backgroundSession {
 56     static NSURLSession *session;
 57     static dispatch_once_t onceToken;
 58     dispatch_once(&onceToken, ^{ //应用程序生命周期内,只执行一次;保证只有一个「后台会话」
 59         //创建会话配置「后台会话」
 60         NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"KMDownloadFile.NSURLSessionDelegateViewController"];
 61         sessionConfiguration.timeoutIntervalForRequest = 60.0; //请求超时时间;默认为60秒
 62         sessionConfiguration.allowsCellularAccess = YES; //是否允许蜂窝网络访问(2G/3G/4G)
 63         sessionConfiguration.HTTPMaximumConnectionsPerHost = 4; //限制每次最多连接数;在 iOS 中默认值为4
 64         sessionConfiguration.discretionary = YES; //是否自动选择最佳网络访问,仅对「后台会话」有效
 65
 66         //创建会话
 67         session = [NSURLSession sessionWithConfiguration:sessionConfiguration
 68                                                 delegate:self
 69                                            delegateQueue:nil];
 70     });
 71     return session;
 72 }
 73
 74 - (void)updateProgress:(int64_t)receiveDataLength totalDataLength:(int64_t)totalDataLength; {
 75     dispatch_async(dispatch_get_main_queue(), ^{ //使用主队列异步方式(主线程)执行更新 UI 操作
 76         if (receiveDataLength == totalDataLength) {
 77             _lblMessage.text = @"下载完成";
 78             kApplication.networkActivityIndicatorVisible = NO;
 79         } else {
 80             _lblMessage.text = @"下载中...";
 81             kApplication.networkActivityIndicatorVisible = YES;
 82             _progVDownloadFile.progress = (float)receiveDataLength / totalDataLength;
 83         }
 84     });
 85 }
 86
 87 - (IBAction)downloadFile:(id)sender {
 88     NSString *fileURLStr = kFileURLStr;
 89     //编码操作;对应的解码操作是用 stringByRemovingPercentEncoding 方法
 90     fileURLStr = [fileURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
 91     NSURL *fileURL = [NSURL URLWithString:fileURLStr];
 92
 93     //创建请求
 94     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL];
 95
 96     //创建会话「进程内会话」;如要用「后台会话」就使用自定义的[self backgroundSession] 方法
 97     NSURLSession *session = [self defaultSession];
 98
 99     //创建下载任务,并且启动他;在非主线程中执行
100     _downloadTask = [session downloadTaskWithRequest:request];
101     [_downloadTask resume];
102
103     /*
104      会话任务状态
105      typedef NS_ENUM(NSInteger, NSURLSessionTaskState) {
106      NSURLSessionTaskStateRunning = 0, //正在执行
107      NSURLSessionTaskStateSuspended = 1, //已挂起
108      NSURLSessionTaskStateCanceling = 2, //正在取消
109      NSURLSessionTaskStateCompleted = 3, //已完成
110      } NS_ENUM_AVAILABLE(NSURLSESSION_AVAILABLE, 7_0);
111      */
112 }
113
114 - (IBAction)cancel:(id)sender {
115     [_downloadTask cancel];
116 }
117
118 - (IBAction)suspend:(id)sender {
119     [_downloadTask suspend];
120     kApplication.networkActivityIndicatorVisible = NO;
121 }
122
123 - (IBAction)resume:(id)sender {
124     [_downloadTask resume];
125 }
126
127 #pragma mark - NSURLSessionDownloadDelegate
128 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
129     NSLog(@"已经接收到响应数据,数据长度为%lld字节...", totalBytesWritten);
130
131     [self updateProgress:totalBytesWritten totalDataLength:totalBytesExpectedToWrite];
132 }
133
134 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
135     //下载文件会临时保存,正常流程下系统最终会自动清除此临时文件;保存路径目录根据会话类型而有所不同:
136     //「进程内会话(默认会话)」和「临时的进程内会话(内存)」,路径目录为:/tmp,可以通过 NSTemporaryDirectory() 方法获取
137     //「后台会话」,路径目录为:/Library/Caches/com.apple.nsurlsessiond/Downloads/com.kenmu.KMDownloadFile
138     NSLog(@"已经接收完所有响应数据,下载后的临时保存路径:%@", location);
139
140     __block void (^updateUI)(); //声明用于主线程更新 UI 的代码块
141
142     NSString *savePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
143     savePath = [savePath stringByAppendingPathComponent:_lblFileName.text];
144     NSURL *saveURL = [NSURL fileURLWithPath:savePath];
145     NSError *saveError;
146     NSFileManager *fileManager = [NSFileManager defaultManager];
147     //判断是否存在旧的目标文件,如果存在就先移除;避免无法复制问题
148     if ([fileManager fileExistsAtPath:savePath]) {
149         [fileManager removeItemAtPath:savePath error:&saveError];
150         if (saveError) {
151             NSLog(@"移除旧的目标文件失败,错误信息:%@", saveError.localizedDescription);
152
153             updateUI = ^ {
154                 _lblMessage.text = @"下载失败";
155             };
156         }
157     }
158     if (!saveError) {
159         //把源文件复制到目标文件,当目标文件存在时,会抛出一个错误到 error 参数指向的对象实例
160         //方法一(path 不能有 file:// 前缀)
161         //                [fileManager copyItemAtPath:[location path]
162         //                                     toPath:savePath
163         //                                      error:&saveError];
164
165         //方法二
166         [fileManager copyItemAtURL:location
167                              toURL:saveURL
168                              error:&saveError];
169
170         if (!saveError) {
171             NSLog(@"保存成功");
172
173             updateUI = ^ {
174                 _lblMessage.text = @"下载完成";
175             };
176         } else {
177             NSLog(@"保存失败,错误信息:%@", saveError.localizedDescription);
178
179             updateUI = ^ {
180                 _lblMessage.text = @"下载失败";
181             };
182         }
183     }
184
185     dispatch_async(dispatch_get_main_queue(), updateUI); //使用主队列异步方式(主线程)执行更新 UI 的代码块
186 }
187
188 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
189     NSLog(@"无论下载成功还是失败,最终都会执行一次");
190
191     if (error) {
192         NSString *desc = error.localizedDescription;
193         NSLog(@"下载失败,错误信息:%@", desc);
194
195         dispatch_async(dispatch_get_main_queue(), ^{ //使用主队列异步方式(主线程)执行更新 UI 操作
196             _lblMessage.text = [desc isEqualToString:@"cancelled"] ? @"下载已取消" : @"下载失败";
197             kApplication.networkActivityIndicatorVisible = NO;
198             _progVDownloadFile.progress = 0.0;
199         });
200     }
201 }
202
203 @end

NSURLSessionDelegateViewController.xib

 

AFNetworkingViewController.h

 1 #import <UIKit/UIKit.h>
 2 #import "MBProgressHUD.h"
 3
 4 @interface AFNetworkingViewController : UIViewController
 5 @property (strong, nonatomic) MBProgressHUD *hud;
 6
 7 @property (strong, nonatomic) IBOutlet UILabel *lblFileName;
 8 @property (strong, nonatomic) IBOutlet UILabel *lblMessage;
 9 @property (strong, nonatomic) IBOutlet UIButton *btnDownloadFileByConnection;
10 @property (strong, nonatomic) IBOutlet UIButton *btnDownloadFileBySession;
11
12 @end 

AFNetworkingViewController.m

  1 #import "AFNetworkingViewController.h"
  2 #import "AFNetworking.h"
  3 #import "AFNetworkActivityIndicatorManager.h"
  4 #import "UIButton+BeautifulButton.h"
  5
  6 @interface AFNetworkingViewController ()
  7 - (void)showAlert:(NSString *)msg;
  8 - (void)checkNetwork;
  9 - (void)layoutUI;
 10 - (NSMutableURLRequest *)downloadRequest;
 11 - (NSURL *)saveURL:(NSURLResponse *)response deleteExistFile:(BOOL)deleteExistFile;
 12 - (void)updateProgress:(int64_t)receiveDataLength totalDataLength:(int64_t)totalDataLength;
 13 @end
 14
 15 @implementation AFNetworkingViewController
 16
 17 - (void)viewDidLoad {
 18     [super viewDidLoad];
 19
 20     [self layoutUI];
 21 }
 22
 23 - (void)didReceiveMemoryWarning {
 24     [super didReceiveMemoryWarning];
 25     // Dispose of any resources that can be recreated.
 26 }
 27
 28 - (void)showAlert:(NSString *)msg {
 29     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"网络情况"
 30                                                     message:msg
 31                                                    delegate:self
 32                                           cancelButtonTitle:nil
 33                                           otherButtonTitles:@"确定", nil];
 34     [alert show];
 35 }
 36
 37 - (void)checkNetwork {
 38     NSURL *baseURL = [NSURL URLWithString:@"http://www.baidu.com/"];
 39     AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL];
 40
 41     NSOperationQueue *operationQueue = manager.operationQueue;
 42     [manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
 43         switch (status) {
 44             case AFNetworkReachabilityStatusReachableViaWiFi:
 45                 [self showAlert:@"Wi-Fi 网络下"];
 46                 [operationQueue setSuspended:NO];
 47                 break;
 48             case AFNetworkReachabilityStatusReachableViaWWAN:
 49                 [self showAlert:@"2G/3G/4G 蜂窝移动网络下"];
 50                 [operationQueue setSuspended:YES];
 51                 break;
 52             case AFNetworkReachabilityStatusNotReachable:
 53             default:
 54                 [self showAlert:@"未连接网络"];
 55                 [operationQueue setSuspended:YES];
 56                 break;
 57         }
 58     }];
 59
 60     [manager.reachabilityManager startMonitoring];
 61 }
 62
 63 - (void)layoutUI {
 64     self.navigationItem.title = kTitleOfAFNetworking;
 65     self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.000];
 66
 67     //条件表达式中,「?:」可以表示在条件不成立的情况,才使用后者赋值,否则使用用于条件判断的前者赋值
 68     //以下语句等同于:UIButton *btn = _btnDownloadFileByConnection ? _btnDownloadFileByConnection : [UIButton new];
 69     //在 .NET 中,相当于使用「??」;在 JavaScript 中,相当于使用「||」来实现这种类似的判断
 70     UIButton *btn = _btnDownloadFileByConnection ?: [UIButton new];
 71     [btn beautifulButton:nil];
 72     [_btnDownloadFileBySession beautifulButton:[UIColor orangeColor]];
 73
 74     //进度效果
 75     _hud = [[MBProgressHUD alloc] initWithView:self.view];
 76     _hud.mode = MBProgressHUDModeDeterminate;
 77     _hud.labelText = @"下载中...";
 78     [_hud hide:YES];
 79     [self.view addSubview:_hud];
 80
 81     //检查网络情况
 82     [self checkNetwork];
 83
 84     //启动网络活动指示器;会根据网络交互情况,实时显示或隐藏网络活动指示器;他通过「通知与消息机制」来实现 [UIApplication sharedApplication].networkActivityIndicatorVisible 的控制
 85     [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
 86 }
 87
 88 - (NSMutableURLRequest *)downloadRequest {
 89     NSString *fileURLStr = kFileURLStr;
 90     //编码操作;对应的解码操作是用 stringByRemovingPercentEncoding 方法
 91     fileURLStr = [fileURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
 92     NSURL *fileURL = [NSURL URLWithString:fileURLStr];
 93
 94     //创建请求
 95     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL];
 96     return request;
 97 }
 98
 99 - (NSURL *)saveURL:(NSURLResponse *)response deleteExistFile:(BOOL)deleteExistFile {
100     NSString *fileName = response ? [response suggestedFilename] : _lblFileName.text;
101
102     //方法一
103 //    NSString *savePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
104 //    savePath = [savePath stringByAppendingPathComponent:fileName];
105 //    NSURL *saveURL = [NSURL fileURLWithPath:savePath];
106
107     //方法二
108     NSURL *saveURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
109     saveURL = [saveURL URLByAppendingPathComponent:fileName];
110     NSString *savePath = [saveURL path];
111
112     if (deleteExistFile) {
113         NSError *saveError;
114         NSFileManager *fileManager = [NSFileManager defaultManager];
115         //判断是否存在旧的目标文件,如果存在就先移除;避免无法复制问题
116         if ([fileManager fileExistsAtPath:savePath]) {
117             [fileManager removeItemAtPath:savePath error:&saveError];
118             if (saveError) {
119                 NSLog(@"移除旧的目标文件失败,错误信息:%@", saveError.localizedDescription);
120             }
121         }
122     }
123
124     return saveURL;
125 }
126
127 - (void)updateProgress:(int64_t)receiveDataLength totalDataLength:(int64_t)totalDataLength; {
128     dispatch_async(dispatch_get_main_queue(), ^{ //使用主队列异步方式(主线程)执行更新 UI 操作
129         _hud.progress = (float)receiveDataLength / totalDataLength;
130
131         if (receiveDataLength == totalDataLength) {
132             _lblMessage.text =  receiveDataLength < 0 ? @"下载失败" : @"下载完成";
133             //kApplication.networkActivityIndicatorVisible = NO;
134             [_hud hide:YES];
135         } else {
136             _lblMessage.text = @"下载中...";
137             //kApplication.networkActivityIndicatorVisible = YES;
138             [_hud show:YES];
139         }
140     });
141 }
142
143 - (IBAction)downloadFileByConnection:(id)sender {
144     //创建请求
145     NSMutableURLRequest *request = [self downloadRequest];
146
147     //创建请求操作
148     AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
149     NSString *savePath = [[self saveURL:nil deleteExistFile:NO] path];
150
151     [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
152         NSLog(@"已经接收到响应数据,数据长度为%lld字节...", totalBytesRead);
153
154         [self updateProgress:totalBytesRead totalDataLength:totalBytesExpectedToRead];
155     }];
156
157     [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
158         NSLog(@"已经接收完所有响应数据");
159
160         NSData *data = (NSData *)responseObject;
161         [data writeToFile:savePath atomically:YES]; //responseObject 的对象类型是 NSData
162
163         [self updateProgress:100 totalDataLength:100];
164     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
165         NSLog(@"下载失败,错误信息:%@", error.localizedDescription);
166
167         [self updateProgress:-1 totalDataLength:-1];
168     }];
169
170     //启动请求操作
171     [operation start];
172 }
173
174 - (IBAction)downloadFileBySession:(id)sender {
175     //创建请求
176     NSMutableURLRequest *request = [self downloadRequest];
177
178     //创建会话配置「进程内会话」
179     NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
180     sessionConfiguration.timeoutIntervalForRequest = 60.0; //请求超时时间;默认为60秒
181     sessionConfiguration.allowsCellularAccess = YES; //是否允许蜂窝网络访问(2G/3G/4G)
182     sessionConfiguration.HTTPMaximumConnectionsPerHost = 4; //限制每次最多连接数;在 iOS 中默认值为4
183
184     //创建会话管理器
185     AFURLSessionManager *sessionManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:sessionConfiguration];
186
187     //创建会话下载任务,并且启动他;在非主线程中执行
188     NSURLSessionDownloadTask *task = [sessionManager
189                                       downloadTaskWithRequest:request
190                                       progress:nil
191                                       destination:^ NSURL*(NSURL *targetPath, NSURLResponse *response) {
192                                           //当 sessionManager 调用 setDownloadTaskDidFinishDownloadingBlock: 方法,并且方法代码块返回值不为 nil 时(优先级高),下面的两句代码是不执行的(优先级低)
193                                           NSLog(@"下载后的临时保存路径:%@", targetPath);
194                                           return [self saveURL:response deleteExistFile:YES];
195                                       } completionHandler:^ (NSURLResponse *response, NSURL *filePath, NSError *error) {
196                                           if (!error) {
197                                               NSLog(@"下载后的保存路径:%@", filePath); //为上面代码块返回的路径
198
199                                               [self updateProgress:100 totalDataLength:100];
200                                           } else {
201                                               NSLog(@"下载失败,错误信息:%@", error.localizedDescription);
202
203                                               [self updateProgress:-1 totalDataLength:-1];
204                                           }
205
206                                           [_hud hide:YES];
207                                       }];
208
209     //类似 NSURLSessionDownloadDelegate 的方法操作
210     //- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;
211     [sessionManager setDownloadTaskDidWriteDataBlock:^ (NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
212         NSLog(@"已经接收到响应数据,数据长度为%lld字节...", totalBytesWritten);
213
214         [self updateProgress:totalBytesWritten totalDataLength:totalBytesExpectedToWrite];
215     }];
216
217     //- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location;
218     [sessionManager setDownloadTaskDidFinishDownloadingBlock:^ NSURL*(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location) {
219         NSLog(@"已经接收完所有响应数据,下载后的临时保存路径:%@", location);
220         return [self saveURL:nil deleteExistFile:YES];
221     }];
222
223     [task resume];
224 }
225
226 @end

AFNetworkingViewController.xib

 View Cod

AppDelegate.h

1 #import <UIKit/UIKit.h>
2
3 @interface AppDelegate : UIResponder <UIApplicationDelegate>
4
5 @property (strong, nonatomic) UIWindow *window;
6 @property (strong, nonatomic) UINavigationController *navigationController;
7
8 @end 

AppDelegate.m

 1 #import "AppDelegate.h"
 2 #import "ViewController.h"
 3
 4 @interface AppDelegate ()
 5
 6 @end
 7
 8 @implementation AppDelegate
 9
10
11 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
12     _window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
13     ViewController *viewController = [[ViewController alloc]
14                                       initWithSampleNameArray:@[ kTitleOfNSURLConnection,
15                                                                  kTitleOfNSURLConnectionDelegate,
16                                                                  kTitleOfNSURLSession,
17                                                                  kTitleOfNSURLSessionDelegate,
18                                                                  kTitleOfAFNetworking]];
19     _navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
20     _window.rootViewController = _navigationController;
21     //[_window addSubview:_navigationController.view]; //当_window.rootViewController关联时,这一句可有可无
22     [_window makeKeyAndVisible];
23     return YES;
24 }
25
26 - (void)applicationWillResignActive:(UIApplication *)application {
27 }
28
29 - (void)applicationDidEnterBackground:(UIApplication *)application {
30 }
31
32 - (void)applicationWillEnterForeground:(UIApplication *)application {
33 }
34
35 - (void)applicationDidBecomeActive:(UIApplication *)application {
36 }
37
38 - (void)applicationWillTerminate:(UIApplication *)application {
39 }
40
41 @end
时间: 2024-10-09 06:38:02

网络文件下载(提供多种下载方式)的相关文章

Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护

Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护 数据加密又称密码学,它是一门历史悠久的技术,指通过加密算法和加密密钥将明文转变为密文,而解密则是通过解密算法和解密密钥将密文恢复为明文.数据加密目前仍是计算机系统对信息进行保护的一种最可靠的办法.它利用密码技术对信息进行加密,实现信息隐蔽,从而起到保护信息的安全的作用. 一.概述 数据加密是指通过加密算法和加密密钥将明文转变为密文,而解密则是通过解密算法和解密密钥将密文恢复为明文.它产生的历史相当久远,它是起源于

iOS开发网络篇—文件下载(五&#183;下载功能的封装)

iOS开发网络篇—文件下载(五·下载功能的封装) 一.简单说明 在前面几篇文章介绍下载代码的基础上,此文分析对下载功能进行封装. 通过之前的代码,我们发现仅仅是下载一个文件就需要写很长的代码,那么如果要下载多个文件,就需要写多份代码.在这里,我们把下载一个文件的代码进行封装.控制器只需要知道,下载哪个文件,下载到哪个路径就可以了. 在对下载的功能进行封装后,添加一个文件下载器,一个文件下载器只下载一个文件,封装后如果要下载多个文件的话,那么只需要创建多个文件下载器对象就可以进行控制和下载了. 二

可删除超炫&amp;多种特效的Card视图(改造自cardsui-for-android开源项目),提供DEMO下载

       这里贴几个效果图,我做了一个gif的动态图,但是不知道为什么上传后图片不动,所以只能放在相册里. 如果大家想看动态的图片演示请点击后面的链接gif动态演示图片 实例Demo下载地址在本文最后 简单介绍 这个Demo主要是使用了cardsui-for-android开源项目,并且做了一些优化和改进: 1.自定义card视图 2.添加长按事件,避免误操作 3.长按后可以删除card,并播放选中动画 4.删除后浮现一个悬浮button 5.点击悬浮button可以恢复之前删除的card视

WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]

原文:WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码和配置:通过ChannelFactory<TChannel>创建服务代理对象.在这篇文章中,我们采用一种独特的方式进行服务的调用.从本质上讲,我们只要能够创建于服务端相匹配的终结点,就能够实现正常的服务调用.在WCF客户端元数据架构体系中,利用MetadataExchangeClient可以获取服

多种下载文件方式 Response.BinaryWrite(byte[] DocContent);Response.WriteFile(System.IO.FileInfo DownloadFile .FullName);Response.Write(string html2Excel);

通过html给xls赋值,并下载xls文件 一.this.Response.Write(sw.ToString());System.IO.StringWriter sw = new System.IO.StringWriter(); this.Response.Clear();            string strFileName;            strFileName = "报表" + ".xls";            Response.Buff

【文件下载】Java下载文件的几种方式

1.以流的方式下载. public HttpServletResponse download(String path, HttpServletResponse response) { try { // path是指欲下载的文件的路径. File file = new File(path); // 取得文件名. String filename = file.getName(); // 取得文件的后缀名. String ext = filename.substring(filename.lastIn

JAVA基础知识之网络编程——-网络基础(多线程下载,get,post)

本文主要介绍java.net下为网络编程提供的一些基础包,InetAddress代表一个IP协议对象,可以用来获取IP地址,Host name之类的信息.URL和URLConnect可以用来访问web资源,URLDecode和URLEncode用来转换字符串. 本文会写两个例子来演示java网络编程的一些基本用法. 第一个例子,写一个程序用来模拟多线程下载. 本例中用到的技术有,多线程--多个线程同时读文件写文件,可以加快下载速度, 线程池--在本例中线程池不是必须,甚至是多余,只不过是为了演示

C#实现文件下载的几种方式

上篇博客也说了下C#中通过XML导出Excel,这些文件操作都挺有用的,下面是文件的下载,之前做项目都是把它写的空间日志中,以后有时间了把它们都弄出来 先把有问题的代码贴出来吧 using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using Sy

iOS开发 -文件下载(5 下载功能的封装)

iOS开发网络篇—文件下载(五·下载功能的封装) 一.简单说明 在前面几篇文章介绍下载代码的基础上,此文分析对下载功能进行封装. 通过之前的代码,我们发现仅仅是下载一个文件就需要写很长的代码,那么如果要下载多个文件,就需要写多份代码.在这里,我们把下载一个文件的代码进行封装.控制器只需要知道,下载哪个文件,下载到哪个路径就可以了. 在对下载的功能进行封装后,添加一个文件下载器,一个文件下载器只下载一个文件,封装后如果要下载多个文件的话,那么只需要创建多个文件下载器对象就可以进行控制和下载了. 二