一 NSURLSessionUploadTask 上传文件大致步骤:
#define Kboundary @"----WebKitFormBoundaryATJp9y6FGSNtJKNW" // 这个是分割符
1> 确定文件上传的路径URL
2> 创建一个NSMutableRequest (request)
3> 设置request 的请求请求方式为 POST
4> 设置请求头信息Content-Type,告诉服务器这时一个上传文件的请求: 分割符是什么
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary] forHTTPHeaderField:@"Content-Type"];
5> 按照固定的格式设置请求体 (请求体包含具体的请求参数 和 要上传的文件数据)
6> 创建Session
7> 使用session 创建NSURLSessionUploadTask
8> 指行task 上传数据
二上传文件请求体详解
- 概览
--分隔符
Content-Disposition: form-data; name="file"; filename="Snip20161126_210.png"
Content-Type: image/png
需要上传的文件数据
--分隔符
Content-Disposition: form-data; name="username"
abc
--分隔符--
- 上传文件请求体分析,其实可以看出是分为3个部分的
1> 第一个部分: 文件参数部分
--分隔符
Content-Disposition: form-data; name="file"; filename="Snip20161126_210.png"
Content-Type: image/png
需要上传的文件数据
2> 第二个部分: 非文件参数部分
--分隔符
Content-Disposition: form-data; name="username"
abc
3> 第三个部分: 结尾标识
--分隔符--
三上传文件实现
- 方式一
#define Kboundary @"----WebKitFormBoundaryATJp9y6FGSNtJKNW" //分隔符
#define KnewLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding] // 换行
-(void)upload1
{
//(1)确定上传路径
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/upload"];
//(2)创建"可变"请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//(3)修改请求方法为POST
request.HTTPMethod = @"POST";
//+ "设置请求头信息,告诉服务器这是一个文件上传请求"
//Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryATJp9y6FGSNtJKNW
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary] forHTTPHeaderField:@"Content-Type"];
//+ "按照固定的格式来拼接数据"
//(4)设置请求体信息(文件参数)
//(5)创建会话对象
NSURLSession *session = [NSURLSession sharedSession];
//(6)根据会话对象来创建uploadTask
/* 参数说明
*
* 第一个参数:请求对象
* 第二个参数:本应该放在请求体中的信息
[self bodyData] 相当于POST请求的 请求体,上传文件时要填写着这个地方,填在 request 的 请求头里是会被忽略的
*/
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:[self bodyData] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
//(7)执行task发送请求上传文件
[uploadTask resume];
}
// 上传文件的请求体
-(NSData *)bodyData
{
NSMutableData *data = [NSMutableData data];
//01 拼接文件参数
/*
--分隔符
Content-Disposition: form-data; name="file"; filename="Snip20161126_210.png"
Content-Type: image/png
空行
文件数据
*/
[data appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
//name:file 服务器规定
//filename:该文件上传到服务器之后的名称
//username|pwd
[data appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"Snip20161126_210.png\"" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
//要上传文件的二进制数据类型 MIMEType 组成:大类型/小类型
[data appendData:[@"Content-Type: image/png" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
[data appendData:KnewLine];
NSData *imageData = [NSData dataWithContentsOfFile:@"/Users/xiaomage/Desktop/Snip20161126_238.png"];
[data appendData:imageData];
[data appendData:KnewLine];
//02 拼接非文件参数
/*
--分隔符
Content-Disposition: form-data; name="username"
空行
abcdf
*/
[data appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
//name:username
[data appendData:[@"Content-Disposition: form-data; name=\"username\"" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
[data appendData:KnewLine];
[data appendData:[@"abcdef" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
//03 结尾标识
/*
--分隔符--
*/
[data appendData:[[NSString stringWithFormat:@"--%@--",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
return data;
}
- 方式二 监听上传进度
#define Kboundary @"----WebKitFormBoundaryATJp9y6FGSNtJKNW"
#define KnewLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]
@interface ViewController ()<NSURLSessionDataDelegate>
-(void)upload2
{
//(1)确定上传路径
NSURL *url = [NSURL URLWithString:@"http://http://127.0.0.1/upload/upload"];
//(2)创建"可变"请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//(3)修改请求方法为POST
request.HTTPMethod = @"POST";
//+ "设置请求头信息,告诉服务器这是一个文件上传请求"
//Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryATJp9y6FGSNtJKNW
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary] forHTTPHeaderField:@"Content-Type"];
//+ "按照固定的格式来拼接数据"
//(4)设置请求体信息(文件参数)
//(5)创建会话对象 设置代理 以便监听上传的进度
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
delegate:self
delegateQueue:[NSOperationQueue mainQueue]];
//(6)根据会话对象来创建uploadTask
/* 参数说明
*
* 第一个参数:请求对象
* 第二个参数:本应该放在请求体中的信息
*/
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:[self bodyData] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
//(7)执行task发送请求上传文件
[uploadTask resume];
}
-(NSData *)bodyData
{
NSMutableData *data = [NSMutableData data];
//01 拼接文件参数
/*
--分隔符
Content-Disposition: form-data; name="file"; filename="Snip20161126_210.png"
Content-Type: image/png
空行
文件数据
*/
[data appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
//name:file 服务器规定
//filename:该文件上传到服务器之后的名称
//username|pwd
[data appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"Snip20161126_210.png\"" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
//要上传文件的二进制数据类型 MIMEType 组成:大类型/小类型
[data appendData:[@"Content-Type: image/png" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
[data appendData:KnewLine];
NSData *imageData = [NSData dataWithContentsOfFile:@"/Users/xiaomage/Desktop/Snip20161126_238.png"];
[data appendData:imageData];
[data appendData:KnewLine];
//02 拼接非文件参数
/*
--分隔符
Content-Disposition: form-data; name="username"
空行
abcdf
*/
[data appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
//name:username
[data appendData:[@"Content-Disposition: form-data; name=\"username\"" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
[data appendData:KnewLine];
[data appendData:[@"abcdef" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:KnewLine];
//03 结尾标识
/*
--分隔符--
*/
[data appendData:[[NSString stringWithFormat:@"--%@--",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
return data;
}
#pragma mark NSURLSessionDataDelegate
-(void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didSendBodyData:(int64_t)bytesSent //本次上传的文件数据大小
totalBytesSent:(int64_t)totalBytesSent //已经上传的文件数据的总大小
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend //文件的总大小
{
NSLog(@"%f",1.0 * totalBytesSent / totalBytesExpectedToSend);
}