首先聲明,利用蘋果自帶的進(jìn)行API進(jìn)行上傳的話,很蛋疼的. 所以一般公司都會(huì)使用原生API進(jìn)行上傳和下載, 用的都是三方框架AFNetwork,ASIHTTPRequest等
現(xiàn)在開始說明利用NSURLConnection
進(jìn)行上傳文件,需要對(duì)請(qǐng)求體進(jìn)行設(shè)置. 只有請(qǐng)求體知道上傳數(shù)據(jù)的格式以及相關(guān)的配置.[蛋疼的是,格式很難寫, 一個(gè)標(biāo)點(diǎn),一個(gè)換行都不能有錯(cuò)誤......] [當(dāng)然可以將邊界進(jìn)行宏定義, 但是對(duì)于邊界必須統(tǒng)一, 而且前面的橫線數(shù)不能少]
/**
* post的上傳文件,不同于普通的數(shù)據(jù)上傳,
* 普通上傳,只是將數(shù)據(jù)轉(zhuǎn)換成二進(jìn)制放置在請(qǐng)求體中,進(jìn)行上傳,有響應(yīng)體得到結(jié)果。
* post上傳,當(dāng)上傳文件是, 請(qǐng)求體中會(huì)多一部分東西, Content——Type,這是在請(qǐng)求體中必須要書寫的,而且必須要書寫正確,不能有一個(gè)標(biāo)點(diǎn)符號(hào)的錯(cuò)誤。負(fù)責(zé)就會(huì)請(qǐng)求不上去,或者出現(xiàn)請(qǐng)求的錯(cuò)誤(無名的問題等)
* 其中在post 請(qǐng)求體中加入的格式有{1、邊界 2、參數(shù) 3、換行 4、具體數(shù)據(jù) 5、換行 6、邊界 7、換行 8、對(duì)象 9、結(jié)束符}
*/
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 設(shè)置請(qǐng)求頭數(shù)據(jù) 。 boundary:邊界
[request setValue:@"multipart/form-data; boundary=----WebKitFormBoundaryftnnT7s3iF7wV5q6" forHTTPHeaderField:@"Content-Type"];
// 給請(qǐng)求體加入固定格式數(shù)據(jù)
NSMutableData *data = [NSMutableData data];
/*******************設(shè)置文件參數(shù)***********************/
// 設(shè)置邊界 注:必須和請(qǐng)求頭數(shù)據(jù)設(shè)置的邊界 一樣, 前面多兩個(gè)“-”;(字符串 轉(zhuǎn) data 數(shù)據(jù))
[data appendData:[@"------WebKitFormBoundaryftnnT7s3iF7wV5q6" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 設(shè)置傳入數(shù)據(jù)的基本屬性, 包括有 傳入方式 data ,傳入的類型(名稱) ,傳入的文件名, 。
[data appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"image.jpeg\"" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 設(shè)置 內(nèi)容的類型 “文件類型/擴(kuò)展名” MIME中的
[data appendData:[@"Content-Type: image/jpeg" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 加入數(shù)據(jù)內(nèi)容
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
UIImage *image = [UIImage imageNamed:@"pause"];
NSData *imageData = UIImagePNGRepresentation(image);
[data appendData:imageData];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 設(shè)置邊界
[data appendData:[@"------WebKitFormBoundaryftnnT7s3iF7wV5q6" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
/******************非文件參數(shù)***************************/
// 內(nèi)容設(shè)置 , 設(shè)置傳入的類型(名稱)
[data appendData:[@"Content-Disposition: form-data; name=\"username\"" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 傳入的名稱username = lxl
[data appendData:[@"lxl" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 退出邊界
[data appendData:[@"------WebKitFormBoundaryftnnT7s3iF7wV5q6--" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
request.HTTPBody = data;
// 設(shè)置請(qǐng)求方式 post
request.HTTPMethod = @"POST";
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
Snip20151003_2.png
1.對(duì)請(qǐng)求頭添加一個(gè)參數(shù);
2.主要是拼接下面的請(qǐng)求體;[數(shù)據(jù)Data]
怎么得到一個(gè)文件的MIME---文件類型/擴(kuò)展名
給NSString添加分類, 主要用于得出文件的MIME[只有在響應(yīng)頭中才有真實(shí)屬性]
+ (NSString *)mimeWithString:(NSString *)string
{
// 先從參入的路徑的出URL
NSURL *url = [NSURL fileURLWithPath:string];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 只有響應(yīng)頭中才有其真實(shí)屬性 也就是MIME
NSURLResponse *response = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
return response.MIMEType;
}
// 在控制器中的調(diào)用
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = @"/Users/liujiaxin/Desktop/image.jpeg";
NSString *mime = [NSString mimeWithString:path];
NSLog(@"%@",mime);
}
對(duì)于上傳文件較大時(shí),我們需要監(jiān)聽它的上傳進(jìn)度,,小文件直接調(diào)用block來返回上傳結(jié)果, 如果需要監(jiān)聽上傳進(jìn)度,則需要進(jìn)行代理處理
代理 -- NSURLConnectionDataDelegate-- 中提供了監(jiān)聽的方法
// totalBytesWritten:目前上傳寫入的文件的大小
// totalBytesExpectedToWrite :預(yù)期需要寫入文件的總大小
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite{
float progress = (float)1.0 * totalBytesWritten / totalBytesExpectedToWrite;
NSLog(@"%f",progress);
}
接下來我們來說明利用NSURLSession怎么來做到文件的上傳.其實(shí)和NSURLConnection大同小異, 都需要拼接蛋疼的東西
NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 設(shè)置請(qǐng)求頭數(shù)據(jù) 。 boundary:邊界
[request setValue:@"multipart/form-data; boundary=----WebKitFormBoundaryftnnT7s3iF7wV5q6" forHTTPHeaderField:@"Content-Type"];
// 給請(qǐng)求頭加入固定格式數(shù)據(jù)
NSMutableData *data = [NSMutableData data];
/****************文件參數(shù)相關(guān)設(shè)置*********************/
// 設(shè)置邊界 注:必須和請(qǐng)求頭數(shù)據(jù)設(shè)置的邊界 一樣, 前面多兩個(gè)“-”;(字符串 轉(zhuǎn) data 數(shù)據(jù))
[data appendData:[@"------WebKitFormBoundaryftnnT7s3iF7wV5q6" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 設(shè)置傳入數(shù)據(jù)的基本屬性, 包括有 傳入方式 data ,傳入的類型(名稱) ,傳入的文件名, 。
[data appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"image.jpeg\"" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 設(shè)置 內(nèi)容的類型 “文件類型/擴(kuò)展名” MIME中的
[data appendData:[@"Content-Type: image/jpeg" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 加入數(shù)據(jù)內(nèi)容
NSData *contentData = [NSData dataWithContentsOfFile:@"/Users/liujiaxin/Desktop/image.jpeg"];
[data appendData:contentData];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 設(shè)置邊界
[data appendData:[@"------WebKitFormBoundaryftnnT7s3iF7wV5q6" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
/******************非文件參數(shù)相關(guān)設(shè)置**********************/
// 設(shè)置傳入的類型(名稱)
[data appendData:[@"Content-Disposition: form-data; name=\"username\"" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 傳入的名稱username = lxl
[data appendData:[@"lxl" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 退出邊界
[data appendData:[@"------WebKitFormBoundaryftnnT7s3iF7wV5q6--" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
request.HTTPBody = data;
request.HTTPMethod = @"POST";
NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:data completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
[task resume];
NSLog(@"+++++++++++++");
}
對(duì)于上傳任務(wù)的監(jiān)聽, 大文件的上傳會(huì)不停的調(diào)用代理方法
---NSURLSessionTaskDelegate--代理方法:
#pragma mark - NSURLSessionTaskDelegate
/**
* 監(jiān)聽上傳進(jìn)度
*
* @param session
* @param task 上傳任務(wù)
* @param bytesSent 當(dāng)前這次發(fā)送的數(shù)據(jù)
* @param totalBytesSent 已經(jīng)發(fā)送的總數(shù)據(jù)
* @param totalBytesExpectedToSend 期望發(fā)送的總數(shù)據(jù)
*/
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
float progress = (float)1.0*totalBytesSent / totalBytesExpectedToSend;
NSLog(@"%f",progress);
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"%s",__func__);
}