文件下载
iOS开发中会经常用到文件上传下载的功能,这篇文件将介绍一下如何结合asp.net webservice实现文件上传下载。
首先,让我们看下文件下载。
这里我们下载cnblogs上的一个zip文件。使用NSURLRequest+NSURLConnection可以很方便的实现这个功能。在 asp.net webservice中可以将文件的地址返回到iOS系统,iOS系统再通过这个url去请求下载该文件。这里为了简单起见,直接将url写道代码里面 了。我们可以使用两种方式去下载文件。
小文件下载
1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 5 // 下载小文件的方式 6 // 1.NSData dataWithContentsOfURL 7 // 2.NSURLConnection 8 } 9 10 // 1.NSData dataWithContentsOfURL 11 - (void)downloadFile 12 { 13 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 14 // 其实这就是一个GET请求 15 NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/images/minion_01.png"]; 16 NSData *data = [NSData dataWithContentsOfURL:url]; 17 NSLog(@"%d", data.length); 18 }); 19 } 20 21 // 2.NSURLConnection 22 - (void)downloadFile2 23 { 24 NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/images/minion_01.png"]; 25 NSURLRequest *request = [NSURLRequest requestWithURL:url]; 26 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { 27 NSLog(@"%d", data.length); 28 }]; 29 }
大文件下载
一:直接下载文件数据
1 - (void)download 2 { 3 // 1.URL 4 NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/videos.zip"]; 5 6 // 2.请求 7 NSURLRequest *request = [NSURLRequest requestWithURL:url]; 8 9 // 3.下载(创建完conn对象后,会自动发起一个异步请求) 10 [NSURLConnection connectionWithRequest:request delegate:self]; 11 12 // [[NSURLConnection alloc] initWithRequest:request delegate:self]; 13 // [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; 14 15 // NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; 16 // [conn start]; 17 } 18 19 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 20 { 21 [self download]; 22 } 23 24 #pragma mark - NSURLConnectionDataDelegate代理方法 25 /** 26 * 请求失败时调用(请求超时、网络异常) 27 * 28 * @param error 错误原因 29 */ 30 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 31 { 32 NSLog(@"didFailWithError"); 33 } 34 35 /** 36 * 1.接收到服务器的响应就会调用 37 * 38 * @param response 响应 39 */ 40 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 41 { 42 NSLog(@"didReceiveResponse"); 43 44 // 初始化数据 45 self.fileData = [NSMutableData data]; 46 47 // 取出文件的总长度 48 // NSHTTPURLResponse *resp = (NSHTTPURLResponse *)response; 49 // long long fileLength = [resp.allHeaderFields[@"Content-Length"] longLongValue]; 50 self.totalLength = response.expectedContentLength; 51 } 52 53 /** 54 * 2.当接收到服务器返回的实体数据时调用(具体内容,这个方法可能会被调用多次) 55 * 56 * @param data 这次返回的数据 57 */ 58 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 59 { 60 // 拼接数据 61 [self.fileData appendData:data]; 62 63 // 设置进度值 64 // 0 ~ 1 65 // self.progressView.progress = (double)self.fileData.length / self.totalLength; 66 self.circleView.progress = (double)self.fileData.length / self.totalLength; 67 } 68 69 /** 70 * 3.加载完毕后调用(服务器的数据已经完全返回后) 71 */ 72 - (void)connectionDidFinishLoading:(NSURLConnection *)connection 73 { 74 NSLog(@"connectionDidFinishLoading"); 75 76 // 拼接文件路径 77 NSString *cache = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; 78 NSString *file = [cache stringByAppendingPathComponent:@"videos.zip"]; 79 80 // 写到沙盒中 81 [self.fileData writeToFile:file atomically:YES]; 82 }
二:下载数据的保存
1 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 2 { 3 // 1.URL 4 NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/music.zip"]; 5 6 // 2.请求 7 NSURLRequest *request = [NSURLRequest requestWithURL:url]; 8 9 // 3.下载(创建完conn对象后,会自动发起一个异步请求) 10 [NSURLConnection connectionWithRequest:request delegate:self]; 11 } 12 13 #pragma mark - NSURLConnectionDataDelegate代理方法 14 /** 15 * 请求失败时调用(请求超时、网络异常) 16 * 17 * @param error 错误原因 18 */ 19 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 20 { 21 NSLog(@"didFailWithError"); 22 } 23 24 /** 25 * 1.接收到服务器的响应就会调用 26 * 27 * @param response 响应 28 */ 29 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 30 { 31 // 文件路径 32 NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; 33 NSString *filepath = [caches stringByAppendingPathComponent:@"videos.zip"]; 34 35 // 创建一个空的文件 到 沙盒中 36 NSFileManager *mgr = [NSFileManager defaultManager]; 37 [mgr createFileAtPath:filepath contents:nil attributes:nil]; 38 39 // 创建一个用来写数据的文件句柄 40 self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filepath]; 41 42 // 获得文件的总大小 43 self.totalLength = response.expectedContentLength; 44 } 45 46 /** 47 * 2.当接收到服务器返回的实体数据时调用(具体内容,这个方法可能会被调用多次) 48 * 49 * @param data 这次返回的数据 50 */ 51 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 52 { 53 // 移动到文件的最后面 54 [self.writeHandle seekToEndOfFile]; 55 56 // 将数据写入沙盒 57 [self.writeHandle writeData:data]; 58 59 // 累计文件的长度 60 self.currentLength += data.length; 61 62 NSLog(@"下载进度:%f", (double)self.currentLength/ self.totalLength); 63 self.circleView.progress = (double)self.currentLength/ self.totalLength; 64 } 65 66 /** 67 * 3.加载完毕后调用(服务器的数据已经完全返回后) 68 */ 69 - (void)connectionDidFinishLoading:(NSURLConnection *)connection 70 { 71 self.currentLength = 0; 72 self.totalLength = 0; 73 74 // 关闭文件 75 [self.writeHandle closeFile]; 76 self.writeHandle = nil; 77 }
断点下载:
1 #pragma mark - NSURLConnectionDataDelegate代理方法 2 /** 3 * 请求失败时调用(请求超时、网络异常) 4 * 5 * @param error 错误原因 6 */ 7 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 8 { 9 NSLog(@"didFailWithError"); 10 } 11 12 /** 13 * 1.接收到服务器的响应就会调用 14 * 15 * @param response 响应 16 */ 17 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 18 { 19 if (self.currentLength) return; 20 21 // 文件路径 22 NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; 23 NSString *filepath = [caches stringByAppendingPathComponent:@"videos.zip"]; 24 25 // 创建一个空的文件 到 沙盒中 26 NSFileManager *mgr = [NSFileManager defaultManager]; 27 [mgr createFileAtPath:filepath contents:nil attributes:nil]; 28 29 // 创建一个用来写数据的文件句柄 30 self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filepath]; 31 32 // 获得文件的总大小 33 self.totalLength = response.expectedContentLength; 34 } 35 36 /** 37 * 2.当接收到服务器返回的实体数据时调用(具体内容,这个方法可能会被调用多次) 38 * 39 * @param data 这次返回的数据 40 */ 41 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 42 { 43 // 移动到文件的最后面 44 [self.writeHandle seekToEndOfFile]; 45 46 // 将数据写入沙盒 47 [self.writeHandle writeData:data]; 48 49 // 累计文件的长度 50 self.currentLength += data.length; 51 52 self.circleView.progress = (double)self.currentLength/ self.totalLength; 53 } 54 55 /** 56 * 3.加载完毕后调用(服务器的数据已经完全返回后) 57 */ 58 - (void)connectionDidFinishLoading:(NSURLConnection *)connection 59 { 60 self.currentLength = 0; 61 self.totalLength = 0; 62 63 // 关闭文件 64 [self.writeHandle closeFile]; 65 self.writeHandle = nil; 66 } 67 68 - (IBAction)download:(UIButton *)sender { 69 // 状态取反 70 sender.selected = !sender.isSelected; 71 72 // 断点续传 73 // 断点下载 74 75 if (sender.selected) { // 继续(开始)下载 76 // 1.URL 77 NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/videos.zip"]; 78 79 // 2.请求 80 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 81 82 // 设置请求头 83 NSString *range = [NSString stringWithFormat:@"bytes=%lld-", self.currentLength]; 84 [request setValue:range forHTTPHeaderField:@"Range"]; 85 86 // 3.下载(创建完conn对象后,会自动发起一个异步请求) 87 self.conn = [NSURLConnection connectionWithRequest:request delegate:self]; 88 } else { // 暂停 89 [self.conn cancel]; 90 self.conn = nil; 91 } 92 }
iOS开发中文件下载可以使用同步和异步下载,但是一般开发中为了良好的用户交互,很少使用同步。
同步下载
1 NSString *urlAsString = @"http://files.cnblogs.com/zhuqil/UIWebViewDemo.zip"; 2 NSURL *url = [NSURL URLWithString:urlAsString]; 3 NSURLRequest *request = [NSURLRequest requestWithURL:url]; 4 NSError *error = nil; 5 NSData *data = http://www.cnblogs.com/zhwl/archive/2012/07/13/[NSURLConnection sendSynchronousRequest:request 6 returningResponse:nil 7 error:&error]; 8 /* 下载的数据 */ 9 if (data != nil){ 10 NSLog(@"下载成功"); 11 if ([data writeToFile:@"UIWebViewDemo.zip" atomically:YES]) { 12 NSLog(@"保存成功."); 13 } 14 else 15 { 16 NSLog(@"保存失败."); 17 } 18 } else { 19 NSLog(@"%@", error); 20 }
异步下载
1 DownLoadingViewController.h 2 3 // DownLoadingViewController.h 4 // DownLoading 5 // 6 // Created by skylin zhu on 11-7-30. 7 // Copyright 2011年 mysoft. All rights reserved. 8 // 9 10 #import 11 12 @interface DownLoadingViewController : UIViewController { 13 NSURLConnection *connection; 14 NSMutableData *connectionData; 15 } 16 @property (nonatomic,retain) NSURLConnection *connection; 17 @property (nonatomic,retain) NSMutableData *connectionData; 18 @end 19 20 DownLoadingViewController.m 21 22 // DownLoadingViewController.m 23 // DownLoading 24 // 25 // Created by skylin zhu on 11-7-30. 26 // Copyright 2011年 mysoft. All rights reserved. 27 // 28 29 #import "DownLoadingViewController.h" 30 31 @implementation DownLoadingViewController 32 @synthesize connection,connectionData; 33 - (void)dealloc 34 { 35 [super dealloc]; 36 } 37 38 - (void)didReceiveMemoryWarning 39 { 40 // Releases the view if it doesn't have a superview. 41 [super didReceiveMemoryWarning]; 42 43 // Release any cached data, images, etc that aren't in use. 44 } 45 46 #pragma mark - View lifecycle 47 48 49 // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 50 - (void)viewDidLoad 51 { 52 [super viewDidLoad]; 53 //文件地址 54 NSString *urlAsString = @"http://files.cnblogs.com/zhuqil/UIWebViewDemo.zip"; 55 NSURL *url = [NSURL URLWithString:urlAsString]; 56 NSURLRequest *request = [NSURLRequest requestWithURL:url]; 57 NSMutableData *data = http://www.cnblogs.com/zhwl/archive/2012/07/13/[[NSMutableData alloc] init]; 58 self.connectionData = http://www.cnblogs.com/zhwl/archive/2012/07/13/data; 59 [data release]; 60 NSURLConnection *newConnection = [[NSURLConnection alloc] 61 initWithRequest:request 62 delegate:self 63 startImmediately:YES]; 64 self.connection = newConnection; 65 [newConnection release]; 66 if (self.connection != nil){ 67 NSLog(@"Successfully created the connection"); 68 } else { 69 NSLog(@"Could not create the connection"); 70 } 71 } 72 73 74 75 76 - (void) connection:(NSURLConnection *)connection 77 didFailWithError:(NSError *)error{ 78 NSLog(@"An error happened"); 79 NSLog(@"%@", error); 80 } 81 - (void) connection:(NSURLConnection *)connection 82 didReceiveData:(NSData *)data{ 83 NSLog(@"Received data"); 84 [self.connectionData appendData:data]; 85 } 86 - (void) connectionDidFinishLoading 87 :(NSURLConnection *)connection{ 88 /* 下载的数据 */ 89 90 NSLog(@"下载成功"); 91 if ([self.connectionData writeToFile:@"UIWebViewDemo.zip" atomically:YES]) { 92 NSLog(@"保存成功."); 93 } 94 else 95 { 96 NSLog(@"保存失败."); 97 } 98 99 /* do something with the data here */ 100 } 101 - (void) connection:(NSURLConnection *)connection 102 didReceiveResponse:(NSURLResponse *)response{ 103 [self.connectionData setLength:0]; 104 } 105 106 - (void) viewDidUnload{ 107 [super viewDidUnload]; 108 [self.connection cancel]; 109 self.connection = nil; 110 self.connectionData = http://www.cnblogs.com/zhwl/archive/2012/07/13/nil; 111 } 112 113 @end