前言:非常繁琐,因为要频繁地拼接参数
#import "ViewController.h"
//分隔符,可以随便写(不能有中文和特殊字符)
#define kboundary @"----WebKitFormBoundaryTXB9yxAAArxFVoHf"
#define KNewLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]
@interface ViewController ()<NSURLSessionDataDelegate>
@end
@implementation ViewController
/*
文件上传(拼接文件参数+拼接非文件参数+结尾标识)
1)设置请求头信息,告诉服务器这是一个文件上传请求,请准备接收我上传的数据
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryTXB9yxAAArxFVoHf
2)POST
3)上传的文件和非文件参数必须要按照固定的格式来拼接
------WebKitFormBoundaryTXB9yxAAArxFVoHf
Content-Disposition: form-data; name="file"; filename="Snip20200808_9.png"
Content-Type: image/png
------WebKitFormBoundaryTXB9yxAAArxFVoHf
Content-Disposition: form-data; name="username"
xiaomage
------WebKitFormBoundaryTXB9yxAAArxFVoHf--
*/
// 文字描述Request Payload中的内容,方便下面用代码写出来(即5.1,5.2,5.3)
/*
分隔符:----WebKitFormBoundaryTXB9yxAAArxFVoHf
1)拼接文件参数
--分隔符
Content-Disposition: form-data; name="file"; filename="Snip20200808_9.png"
Content-Type: image/png
空行
文件参数
2)拼接非文件参数
--分隔符
Content-Disposition: form-data; name="username"
空行
xiaomage(非文件参数)
3)结尾标识
--分隔符--
*/
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self upload];
}
-(void)upload
{
//1.确定URL
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
//2.创建可变的请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//3.修改请求方法为POST
request.HTTPMethod = @"POST";
//4.设置请求头信息,上传请求
NSString *header = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",kboundary];
[request setValue:header forHTTPHeaderField:@"Content-Type"];
//6.创建会话对象,设置代理
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//7.创建Task(dataTask downloadTask uploadTask:dataTask)
/*
第一个参数:请求对象
第二个参数:要上传的数据
*/
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:[self getBody] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//9.解析服务器返回的响应体信息
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
//8.执行Task
[uploadTask resume];
}
//注意这个是有返回值类型的方法
-(NSData *)getBody
{
//5.拼接数据
NSMutableData *uploadData = [NSMutableData data];
//5.1 拼接文件参数
/*
--分隔符
Content-Disposition: form-data; name="file"; filename="Snip20200808_9.png"
Content-Type: image/png
空行
文件参数
*/
//stringWithFormat后面一定为6个-
[uploadData appendData:[[NSString stringWithFormat:@"--%@",kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[uploadData appendData:KNewLine];
//http://120.25.226.186:32812/login?username=123&pwd=123&type=JSON
//username和pwd以及type是参数的名称
//ZB|123|JSON参数对应的值
//file参数名称(是固定的,由当前的服务器规定的)
//文件参数---值
//filename:Snip20200808_9.png该文件在服务器上面以什么名称保存
[uploadData appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"123.png\"" dataUsingEncoding:NSUTF8StringEncoding]];
[uploadData appendData:KNewLine];
[uploadData appendData:[@"Content-Type: image/png" dataUsingEncoding:NSUTF8StringEncoding]];
[uploadData appendData:KNewLine];
[uploadData appendData:KNewLine];
//要上传的图片的名字
UIImage *image = [UIImage imageNamed:@"Snip20200808_12"];
NSData *imageData = UIImagePNGRepresentation(image);
[uploadData appendData:imageData];
[uploadData appendData:KNewLine];
//5.2 拼接非文件参数
/*
--分隔符
Content-Disposition: form-data; name="username"
空行
xiaomage(非文件参数)
*/
[uploadData appendData:[[NSString stringWithFormat:@"--%@",kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[uploadData appendData:KNewLine];
//username 参数名称
//xiaomage 值
[uploadData appendData:[@"Content-Disposition: form-data; name=\"username\"" dataUsingEncoding:NSUTF8StringEncoding]];
[uploadData appendData:KNewLine];
[uploadData appendData:KNewLine];
[uploadData appendData:[@"CoderZb" dataUsingEncoding:NSUTF8StringEncoding]];//多余?多余?多余?
[uploadData appendData:KNewLine];
//5.3 拼接结尾标识
// --分隔符-- 前面6个-,后面2个-
[uploadData appendData:[[NSString stringWithFormat:@"--%@--",kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
return uploadData;
}
#pragma mark --------------------
#pragma mark NSURLSessionDataDelegate
//bytesSent 表示本次上传文件数据的大小
//totalBytesSent 已经上传的文件大小
//totalBytesExpectedToSend:文件的总大小
-(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);
}
@end
截图

31-14.gif