关键代码记录
NSDictionary *params = @{@"type" : @"1"};
GODebugLog(@"path : %@", path);
/// ********************************************************************************
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: path] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
// 1、组装 http body ===================
// ①定义分界线(boundary)
NSString *boundaryID = [[NSString stringWithFormat:@"boundary_cba_cfrdce_%@_%@", @(arc4random()), @(arc4random())] md5]; // 分界线标识符
NSString *boundary = [NSString stringWithFormat:@"--%@", boundaryID]; // 分界线
NSString *boundaryEnding = [NSString stringWithFormat:@"--%@--", boundaryID]; // 分界线结束
// ②图片data
NSData *imgData = UIImageJPEGRepresentation(pic, 0.5);
// ③http body的字符串
NSMutableString *bodyString = [NSMutableString string];
// 遍历keys,组装文本类型参数
NSArray *keys = [params allKeys];
for (NSString *key in keys) {
// 添加分界线,换行
[bodyString appendFormat:@"%@\r\n", boundary];
// 添加参数名称,换2行
[bodyString appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key];
// 添加参数的值,换行
[bodyString appendFormat:@"%@\r\n", [params objectForKey:key]];
}
// 添加分界线,换行
[bodyString appendFormat:@"%@\r\n", boundary];
// 组装文件类型参数, 换行
NSString *fileParamName = @"file"; // 文件参数名
NSString *filename = @"avatar.jpg"; // 文件名
[bodyString appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fileParamName, filename];
// 声明上传文件的格式,换2行
NSString *fileType = @"image/jpeg";
[bodyString appendFormat:@"Content-Type: %@\r\n\r\n", fileType];
// 声明 http body data
NSMutableData *bodyData = [NSMutableData data];
// 将 body 字符串 bodyString 转化为UTF8格式的二进制数据
NSData *bodyParamData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
[bodyData appendData:bodyParamData];
// 将 image 的 data 加入
[bodyData appendData:imgData];
[bodyData appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; // image数据添加完后 加一个换行
// 分界线结束符加入(以 NSData 形式)
NSString *boundryEndingWithReturn = [NSString stringWithFormat:@"%@\r\n", boundaryEnding]; // 分界线结束符加换行
NSData *boundryEndingData = [boundryEndingWithReturn dataUsingEncoding:NSUTF8StringEncoding];
[bodyData appendData:boundryEndingData];
// 设置 http body data
request.HTTPBody = bodyData;
// 组装 http body 结束 ===================
// 设置 http header 中的 Content-Type 的值
NSString *content = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundaryID];
[request setValue:content forHTTPHeaderField:@"Content-Type"];
// 设置 Content-Length
[request setValue:[NSString stringWithFormat:@"%@", @(bodyData.length)] forHTTPHeaderField:@"Content-Length"];
// 设置请求方式 POST
request.HTTPMethod = @"POST";
// 三种方式都可以发起请求
#if 0 // NSURLConnection
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
GODebugLog(@"response : %@", response);
GODebugLog(@"data : %@", data);
GODebugLog(@"connectionError : %@", connectionError);
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"dic : %@", dic);
success(dic);
}];
#elif 1 // NSURLSessionUploadTask
NSURLSessionUploadTask *uploadTask = [[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:bodyData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
GODebugLog(@"data : %@", data);
GODebugLog(@"response : %@", response);
GODebugLog(@"error : %@", error);
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"dic : %@", dic);
success(dic);
}];
[uploadTask resume];
#else // NSURLSessionDataTask
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
GODebugLog(@"data : %@", data);
GODebugLog(@"response : %@", response);
GODebugLog(@"error : %@", error);
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"dic : %@", dic);
success(dic);
}];
[dataTask resume];
#endif
前一种方式拼接方式为将所有参数及参数的值(除去文件参数)拼接成一个NSString,然后再一起转换为NSData,也可以将每一个参数和参数值分别转换为NSData,逐个将NSData拼接到一起,两种方式结果是一致的。
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:30];
[request setHTTPMethod:@"POST"];
NSString *boundaryID = [[NSString stringWithFormat:@"boundary_cba_cfrdce_%@_%@", @(arc4random()), @(arc4random())] md5]; // 分界线标识符
// set Content-Type in HTTP header
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundaryID];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
// post body
NSMutableData *body = [NSMutableData data];
// add params (all params are strings)
for (NSString *param in params) {
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundaryID] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", param] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", [params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];
}
if (imageData) {
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundaryID] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"image.jpg\"\r\n", @"file"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:imageData];
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
}
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundaryID] dataUsingEncoding:NSUTF8StringEncoding]];
// setting the body of the post to the reqeust
[request setHTTPBody:body];
// set the content-length
NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[body length]];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
// set URL
[request setURL:[NSURL URLWithString: path]];
// 三种方式都可以发起请求
#if 0 // NSURLConnection
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
GODebugLog(@"response : %@", response);
GODebugLog(@"data : %@", data);
GODebugLog(@"connectionError : %@", connectionError);
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"dic : %@", dic);
success(dic);
}];
#elif 1 // NSURLSessionUploadTask
NSURLSessionUploadTask *uploadTask = [[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:bodyData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
GODebugLog(@"data : %@", data);
GODebugLog(@"response : %@", response);
GODebugLog(@"error : %@", error);
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"dic : %@", dic);
success(dic);
}];
[uploadTask resume];
#else // NSURLSessionDataTask
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
GODebugLog(@"data : %@", data);
GODebugLog(@"response : %@", response);
GODebugLog(@"error : %@", error);
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"dic : %@", dic);
success(dic);
}];
[dataTask resume];
#endif