NSURLConnection實現文件上傳
- 文件上傳步驟
1.
確定請求路徑
2.
根據URL創建一個可變的請求對象
3.
設置請求對象,修改請求方式為POST
4.
設置請求頭,告訴服務器我們將要上傳文件(Content-Type)
5.
設置請求體(在請求體中按照既定的格式拼接要上傳的文件參數和非文件參數等數據)- 拼接文件參數
- 拼接非文件參數
- 添加結尾標記
6.
使用NSURLConnection sendAsync發送異步請求上傳文件
7.
解析服務器返回的數據
- 文件上傳設置請求體的數據格式
//請求體拼接格式
//分隔符:----WebKitFormBoundaryhBDKBUWBHnAgvz9c
//01.文件參數拼接格式
--分隔符
Content-Disposition:參數
Content-Type:參數
空行
文件參數
//02.非文件拼接參數
--分隔符
Content-Disposition:參數
空行
非文件的二進制數據
//03.結尾標識
--分隔符--
- 文件上傳相關代碼
-(void)upload {
//1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"URL字符串"];
//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]);
}];
}
- 如何獲得文件的MIMEType類型
- 直接對該對象發送一個異步網絡請求,在響應頭中通過response.MIMEType拿到文件的MIMEType類型
//如果想要及時拿到該數據,那么可以發送一個同步請求
-(NSString *)getMIMEType{
NSString *filePath = @"文件所在路徑";
NSURLResponse *response = nil;
[NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:filePath]] returningResponse:&response error:nil];
return response.MIMEType;
}
//對該文件發送一個異步請求,拿到文件的MIMEType
-(void)MIMEType{
// NSString *file = @"文件所在路徑";
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:@"/Users/文頂頂/Desktop/test.png"]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * __nullable response, NSData * __nullable data, NSError * __nullable connectionError) {
// response.MIMEType
NSLog(@"%@",response.MIMEType);
}];
}
- 通過UTTypeCopyPreferredTagWithClass方法
//注意:需要依賴于框架MobileCoreServices
-(NSString *)mimeTypeForFileAtPath:(NSString *)path{
if (![[[NSFileManager alloc] init] fileExistsAtPath:path]) {
return nil;
}
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[path pathExtension], NULL); CFStringRef MIMEType = UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType);
CFRelease(UTI);
if (!MIMEType) {
return @"application/octet-stream";
}
return (__bridge NSString *)(MIMEType);
}
NSURLSession實現文件上傳
- 實現文件上傳的方法
/*
第一個參數:請求對象
第二個參數:請求體(要上傳的文件數據)
block回調:
NSData:響應體
NSURLResponse:響應頭
NSError:請求的錯誤信息
*/
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:data completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error)
- 設置代理,在代理方法中監聽文件上傳進度
/*
調用該方法上傳文件數據
如果文件數據很大,那么該方法會被調用多次
參數說明:
totalBytesSent:已經上傳的文件數據的大小
totalBytesExpectedToSend:文件的總大小
*/
-(void)URLSession:(nonnull NSURLSession *)session task:(nonnull NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
NSLog(@"%.2f",1.0 * totalBytesSent/totalBytesExpectedToSend);
}
- 關于NSURLSessionConfiguration相關
- 作用:可以統一配置NSURLSession,如請求超時等
- 創建的方式和使用
//創建配置的三種方式
+(NSURLSessionConfiguration *)defaultSessionConfiguration;
+(NSURLSessionConfiguration *)ephemeralSessionConfiguration;
+(NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier NS_AVAILABLE(10_10, 8_0);
//統一配置NSURLSession
-(NSURLSession *)session
{
if (_session == nil) {
//創建NSURLSessionConfiguration
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
//設置請求超時為10秒鐘
config.timeoutIntervalForRequest = 10;
//在蜂窩網絡情況下是否繼續請求(上傳或下載)
config.allowsCellularAccess = NO;
_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}