开篇,先安利一下关于POST与GET这两种请求方式在使用过程中应该知道的优缺点,是知乎里面的一个问题讨论。【POST相比GET有很多优点,为什么现在的HTTP通信中大多数请求还是使用GET?】
#define HTTP_CONTENT_BOUNDARY @"----WebKitFormBoundarywpMAGHPPMfSNBkkK----"
+ (BOOL)httpPutDataWithUploadDate:(NSString *)uploadDate UserName:(NSString *)userName FilePath:(NSString *)filePath{
NSString *strUrl = [clsOtherFun getUploadCrashFileURL];
strUrl = [strUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:strUrl];
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSString *fileName = [filePath lastPathComponent];
NSMutableString *bodyStr = [[NSMutableString alloc] init];
[bodyStr appendString:[NSString stringWithFormat:@"--%@\nContent-Disposition: form-data; name=\"UploadDate\";\n\n%@\n", HTTP_CONTENT_BOUNDARY, uploadDate]];
[bodyStr appendString:[NSString stringWithFormat:@"--%@\nContent-Disposition: form-data; name=\"UserName\";\n\n%@\n", HTTP_CONTENT_BOUNDARY, userName]];
[bodyStr appendString:[NSString stringWithFormat:@"--%@\nContent-Disposition: form-data; name=\"System\";\n\niOS\n", HTTP_CONTENT_BOUNDARY]];
[bodyStr appendString:[NSString stringWithFormat:@"--%@\nContent-Disposition: form-data; name=\"%@\"; filename=\"%@\"\nContent-Type: %@\n\n",HTTP_CONTENT_BOUNDARY, @"file1", fileName, @"text/plain"]];
NSMutableData *httpBody = [NSMutableData data];
[httpBody appendData:[bodyStr dataUsingEncoding:NSUTF8StringEncoding]];
[httpBody appendData:data];
[httpBody appendData:[[NSString stringWithFormat:@"\n--%@",HTTP_CONTENT_BOUNDARY] dataUsingEncoding:NSUTF8StringEncoding]];
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] init];
[urlRequest setURL:url];
[urlRequest setHTTPMethod:@"POST"];
[urlRequest setTimeoutInterval: 60000];
[urlRequest setValue:[NSString stringWithFormat:@"%@", @(httpBody.length)] forHTTPHeaderField:@"Content-Length"];
[urlRequest setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",HTTP_CONTENT_BOUNDARY] forHTTPHeaderField:@"Content-Type"];
urlRequest.HTTPBody = httpBody;
NSHTTPURLResponse *httpResponse = nil;
NSError *error = [[NSError alloc] init];
NSData *responseData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&httpResponse error:&error];
if (responseData != nil) {
// NSMutableDictionary *dict = NULL;
//IOS5自带解析类NSJSONSerialization从response中解析出数据放到字典中
// NSString *responseStr = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&error];
//若状态码为200,则服务器访问成功!
if (httpResponse == nil) {
NSLog(@"url: %@\nerror_code: %@", strUrl, error);
}
if (httpResponse.statusCode != 200) {
NSLog(@"url: %@\nHTTP response: %ld", strUrl, (long)httpResponse.statusCode);
}
//若后台返回字符串“1”,则文件上传成功!
NSString *resultStr = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
if (httpResponse.statusCode == 200 && [resultStr isEqualToString:@"1"]) {
return YES;
}
else{
return NO;
}
NSLog(@"upload_file_resultStr: %@", resultStr);
}
return NO;
}
这是我用Safari截取的POST请求的表单流格式,见下图:
(因后台服务器提供的接口已不可访问,故显示的内容不太契合。若访问正常,则“No user permission.”显示为下图的内容。)
上面就是需要拼接的表单流格式。注意:一定要严格遵循这种格式!
图中每个框框的内容为对应参数的格式。
这时候只需要我们拼接的参数、字符串格式是严格遵循以上格式。
上面的代码不免显得臃肿,也难以通用。
下面介绍一种更为简单便捷的方式,当然同样基于POST请求。没错,主角就是AFNetworking,AFHTTPSessionManager为我们提供了
*- (NSURLSessionDataTask )POST:(NSString *)URLString
parameters:(id)parameters
constructingBodyWithBlock:(void (^)(id formData))block
progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask task, NSError *error))failure*
这一方法,自从用了它,我们的代码处理一切都变得简单起来。
关键代码:
AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
session.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:
@"application/json",
@"text/json",
@"text/javascript",
@"text/html",
@"text/plain",
nil];
[session POST:[Utils getVerificationURL]
//我们的参数集合
parameters:@{@"UserID":userIDStr,
@"IDNumber":idNumStr,
@"RealName":realNameStr,
@"File1":fileName1,
@"File2":fileName2}
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:photoData1 name:@"File1"
fileName:fileName1 mimeType:@"image/jpeg"];
[formData appendPartWithFileData:photoData2 name:@"File2"
fileName:fileName2 mimeType:@"image/jpeg"];
}
progress:^(NSProgress * _Nonnull uploadProgress) {
NSLog(@"service progress...");
}
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (responseObject != nil) {
// {"Code":1,"Msg":"1.成功; 3.用户不存在或无效; 4.用户已经完成审核; 5.写入数据失败 "}
// 若后台返回"Code"字段为“1”,则文件上传成功!
NSLog(@"POST Response Code:%@", [responseObject valueForKey:@"Code"]);
//responseObject的格式已经为JSON数据格式。
if ([[responseObject valueForKey:@"Code"] integerValue] == 1){
//do you what you want.
//[session invalidateSessionCancelingTasks:YES];
}
}
}
failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"POST Error: %@", error.description);
}
];
}
文章难免会有纰漏之处,若有发现,还望各位同仁提出。让我们共同交流,一起进步!