一:輸出流
#import "ViewController.h" @interface ViewController ()<NSURLConnectionDataDelegate> @property (weak, nonatomic) IBOutlet UIProgressView *progressView; @property (nonatomic, assign) NSInteger totalSize; @property (nonatomic, assign) NSInteger currentSize; /** 沙盒路徑 */ @property (nonatomic, strong) NSString *fullPath; /** 連接對象 */ @property (nonatomic, strong) NSURLConnection *connect; /** 輸出流*/ @property (nonatomic, strong) NSOutputStream *stream; @end @implementation ViewController - (IBAction)startBtnClick:(id)sender { [self download]; } - (IBAction)cancelBtnClick:(id)sender { [self.connect cancel]; } - (IBAction)goOnBtnClick:(id)sender { [self download]; } //內存飆升 -(void)download { //1.url // NSURL *url = [NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=54a8cc6f728b4710ce2ffdc4f3cec3b2/d143ad4bd11373f06c0b5bd1a40f4bfbfbed0443.jpg"]; NSURL *url = [NSURL URLWithString:@"http://www.33lc.com/article/UploadPic/2012-10/2012102514201759594.jpg"]; //2.創建請求對象 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; //設置請求頭信息,告訴服務器值請求一部分數據range /* bytes=0-100 bytes=-100 bytes=0- 請求100之后的所有數據 */ NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentSize]; [request setValue:range forHTTPHeaderField:@"Range"]; NSLog(@"+++++++%@",range); //3.發送請求 NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:request delegate:self]; self.connect = connect; } #pragma mark ---------------------- #pragma mark NSURLConnectionDataDelegate -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSLog(@"didReceiveResponse"); //1.得到文件的總大小(本次請求的文件數據的總大小 != 文件的總大小) // self.totalSize = response.expectedContentLength + self.currentSize; if (self.currentSize >0) { return; } self.totalSize = response.expectedContentLength; //2.寫數據到沙盒中 self.fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"123.jpg"]; NSLog(@"%@",self.fullPath); //3.創建輸出流 // NSOutputStream // NSInputStream /* 第一個參數:文件的路徑 第二個參數:YES 追加 特點:如果該輸出流指向的地址沒有文件,那么會自動創建一個空的文件 */ NSOutputStream *stream = [[NSOutputStream alloc]initToFileAtPath:self.fullPath append:YES]; //打開輸出流 [stream open]; self.stream = stream; } -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { //寫數據 [self.stream write:data.bytes maxLength:data.length]; //3.獲得進度 self.currentSize += data.length; //進度=已經下載/文件的總大小 NSLog(@"%f",1.0 * self.currentSize/self.totalSize); self.progressView.progress = 1.0 * self.currentSize/self.totalSize; //NSLog(@"%@",self.fullPath); } -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { } -(void)connectionDidFinishLoading:(NSURLConnection *)connection { //關閉流 [self.stream close]; self.stream = nil; NSLog(@"connectionDidFinishLoading"); NSLog(@"%@",self.fullPath); } @end
#####7.0 輸出流
(1)使用輸出流也可以實現和NSFileHandle相同的功能
(2)如何使用
```objc
//1.創建一個數據輸出流
/*
第一個參數:二進制的流數據要寫入到哪里
第二個參數:采用什么樣的方式寫入流數據,如果YES則表示追加,如果是NO則表示覆蓋
*/
NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath:fullPath append:YES];
//只要調用了該方法就會往文件中寫數據
//如果文件不存在,那么會自動的創建一個
[stream open];
self.stream = stream;
//2.當接收到數據的時候寫數據
//使用輸出流寫數據
/*
第一個參數:要寫入的二進制數據
第二個參數:要寫入的數據的大小
*/
[self.stream write:data.bytes maxLength:data.length];
//3.當文件下載完畢的時候關閉輸出流
//關閉輸出流
[self.stream close];
self.stream = nil;
```
二:文件上傳
//文件上傳步驟 /** * 1:NSURLConnection的post請求:1:需要初始化url確定請求路徑,設置可變請求對象NSMutableURLRequest,設置請求方式post,設置請求頭,設置請求體,發送異步請求文件上傳 */ /* 1.設置請求頭 :boundary為分隔符 Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryjv0UfA04ED44AhWx 2.按照固定的格式拼接請求體的數據 ------WebKitFormBoundaryjv0UfA04ED44AhWx Content-Disposition: form-data; name="file"; filename="Snip20160225_341.png" Content-Type: image/png ------WebKitFormBoundaryjv0UfA04ED44AhWx Content-Disposition: form-data; name="username" 123456 ------WebKitFormBoundaryjv0UfA04ED44AhWx-- */ //拼接請求體的數據格式 /* 拼接請求體 分隔符:----WebKitFormBoundaryjv0UfA04ED44AhWx 1)文件參數 --分隔符 Content-Disposition: form-data; name="file"; filename="Snip20160225_341.png" Content-Type: image/png(MIMEType:大類型/小類型) 空行 文件參數 2)非文件參數 --分隔符 Content-Disposition: form-data; name="username" 空行 123456 3)結尾標識 --分隔符-- */ #import "ViewController.h" #define Kboundary @"----WebKitFormBoundaryjv0UfA04ED44AhWx" #define KNewLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding] @interface ViewController () @end @implementation ViewController -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self upload]; } -(void)upload { //1.確定請求路徑 NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"]; //2.創建可變的請求對象 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; //3.設置請求方法 request.HTTPMethod = @"POST"; //4.設置請求頭信息 //Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryjv0UfA04ED44AhWx [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary] forHTTPHeaderField:@"Content-Type"]; //5.拼接請求體數據 NSMutableData *fileData = [NSMutableData data]; //5.1 文件參數 /* --分隔符 Content-Disposition: form-data; name="file"; filename="Snip20160225_341.png" Content-Type: image/png(MIMEType:大類型/小類型) 空行 文件參數 */ //字符串轉碼:dataUsingEncoding [fileData appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]]; [fileData appendData:KNewLine]; //name:file 服務器規定的參數 //filename:Snip20160225_341.png 文件保存到服務器上面的名稱 //Content-Type:文件的類型 //其中的\代表轉義,對雙引號進行轉義 [fileData appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"Snip20160225_341.png\"" dataUsingEncoding:NSUTF8StringEncoding]]; [fileData appendData:KNewLine]; [fileData appendData:[@"Content-Type: image/png" dataUsingEncoding:NSUTF8StringEncoding]]; [fileData appendData:KNewLine]; [fileData appendData:KNewLine]; UIImage *image = [UIImage imageNamed:@"Snip20160225_341"]; /** * 1:將image轉化成data的格式:UIImagePNGRepresentation或是jpeg * */ //UIImage --->NSData NSData *imageData = UIImagePNGRepresentation(image); [fileData appendData:imageData]; [fileData appendData:KNewLine]; //5.2 非文件參數 /* --分隔符 Content-Disposition: form-data; name="username" 空行 123456 */ [fileData appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]]; [fileData appendData:KNewLine]; [fileData appendData:[@"Content-Disposition: form-data; name=\"username\"" dataUsingEncoding:NSUTF8StringEncoding]]; [fileData appendData:KNewLine]; [fileData appendData:KNewLine]; [fileData appendData:[@"123456" dataUsingEncoding:NSUTF8StringEncoding]]; [fileData appendData:KNewLine]; //5.3 結尾標識 /* --分隔符-- */ [fileData appendData:[[NSString stringWithFormat:@"--%@--",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]]; //6.設置請求體 request.HTTPBody = fileData; //7.發送請求 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) { //8.解析數據 NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); }]; } @end
#####10.0 文件的上傳
- 10.1 文件上傳步驟
(1)確定請求路徑
(2)根據URL創建一個可變的請求對象
(3)設置請求對象,修改請求方式為POST
(4)設置請求頭,告訴服務器我們將要上傳文件(Content-Type)
(5)設置請求體(在請求體中按照既定的格式拼接要上傳的文件參數和非文件參數等數據)
001 拼接文件參數
002 拼接非文件參數
003 添加結尾標記
(6)使用NSURLConnection sendAsync發送異步請求上傳文件
(7)解析服務器返回的數據
- 10.2 文件上傳設置請求體的數據格式
//請求體拼接格式
//分隔符:----WebKitFormBoundaryhBDKBUWBHnAgvz9c
//01.文件參數拼接格式
--分隔符
Content-Disposition:參數
Content-Type:參數
空行
文件參數
//02.非文件拼接參數
--分隔符
Content-Disposition:參數
空行
非文件的二進制數據
//03.結尾標識
--分隔符--
- 10.3 文件上傳相關代碼
```objc
- (void)upload
{
//1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
//2.創建一個可變的請求對象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//3.設置請求方式為POST
request.HTTPMethod = @"POST";
//4.設置請求頭
NSString *filed = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary];
[request setValue:filed forHTTPHeaderField:@"Content-Type"];
//5.設置請求體
NSMutableData *data = [NSMutableData data];
//5.1 文件參數
/*
--分隔符
Content-Disposition:參數
Content-Type:參數
空行
文件參數
*/
[data appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
[data appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"test.png\"" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
[data appendData:[@"Content-Type: image/png" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
[data appendData:KnewLine];
[data appendData:KnewLine];
UIImage *image = [UIImage imageNamed:@"test"];
NSData *imageData = UIImagePNGRepresentation(image);
[data appendData:imageData];
[data appendData:KnewLine];
//5.2 非文件參數
/*
--分隔符
Content-Disposition:參數
空行
非文件參數的二進制數據
*/
[data appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
[data appendData:[@"Content-Disposition: form-data; name=\"username\"" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
[data appendData:KnewLine];
[data appendData:KnewLine];
NSData *nameData = [@"wendingding" dataUsingEncoding:NSUTF8StringEncoding];
[data appendData:nameData];
[data appendData:KnewLine];
//5.3 結尾標識
//--分隔符--
[data appendData:[[NSString stringWithFormat:@"--%@--",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
request.HTTPBody = data;
//6.發送請求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * __nullable response, NSData * __nullable data, NSError * __nullable connectionError) {
//7.解析服務器返回的數據
NSLog(@"%@",[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}];
}
```
