IOS 基于 NSURLSession 进行 HTTP 请求
前言
使用 IOS 内置控件 NSURLSession 进行 HTTP GET 请求,POST 请求,文件的上传与下载,TCP 连接等。
本文将对这些请求进行介绍与举例。
GET 请求
HTTP GET 请求只需要传递 header 即可,封装在 header 中的 URL 承担了传递参数的作用,与此同时,也意味着这些参数将直接暴露给外界。
// 1. 创建 HTTP 请求对象
// 创建请求路径 - URL 的格式
NSURL *url=[NSURL URLWithString:@"http://172.18.176.202:3333/user?id=1"];
// 创建 Request 对象,设置请求 url
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 默认 Type 为 GET,因此无需设置 HTTPMethod
// 2. 发送 HTTP 请求
// 创建会话
NSURLSession *session=[NSURLSession sharedSession];
// 发起任务(Task)
NSURLSessionDataTask *dataTask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// ...
}];
// 结束任务 !!!
[dataTask resume];
POST 请求
以 application/json 数据段格式的 POST 请求为例
application/json 格式的数据段,适合一般数据的传输,如:字符串,数字等。只需使用 NSDictionary 创建字典对象,再将其序列化为 JSON 格式数据即可。
// 1. 创建 HTTP 请求对象
// 创建请求路径 - URL 的格式
NSURL *url=[NSURL URLWithString:@"http://172.18.176.202:3333/hw3/signup"];
// 创建 Request 对象,设置请求 url + type
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"POST"];
// 处理传入的参数,先使用 NSDictionary 创建一个包含请求参数键值对的字典对象
NSDictionary *dic = @{@"name" : self.textFieldA.text,
@"pwd" : self.textFieldB.text};
// 使用 NSJSONSerialization 将字典对象转为 json 字符串
NSData *data_login = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
// 设置请求的 body 部分(数据段)
request.HTTPBody = data_login;
// 2. 发送 HTTP 请求
// 创建会话
NSURLSession *session=[NSURLSession sharedSession];
// 发起任务(Task)
NSURLSessionDataTask *dataTask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 接收服务器传回的数据对象(JSON 格式)
id returnda=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
// 创建一个线程处理数据
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// 先将 JSON 数据直接强制转为字典对象
NSDictionary *dict=(NSDictionary *)returnda;
// 使用 dict[@"XXX"] 获取 JSON 对象某个字段的数据
if (![dict[@"msg"] isEqualToString:@"success"]){
// 登录失败
}else {
// 登录成功
}
}];
}];
// 结束任务 !!!
[dataTask resume];
可以看到 使用 NSURLSession 进行 HTTP 请求有三个步骤:
- 创建请求(NSMutableURLRequest),这里需要我们加入请求的 URL,请求的数据类型和请求类型(POST、GET 等)。然后还需要加入 JSON 格式的数据(作为传入的参数),这里比较方便的方法就是先创建一个 NSDictionary 对象,把我们数据按字段填进去,然后 使用 NSJSONSerialization 进行序列化。
- 创建 NSURLSession 对象,然后发起 NSURLSessionDataTask,向服务器发起请求,并获取返回的数据。
- 最后,先将回调数据转为 JSON 对象,然后直接转为 NSDictionary 对象,就可以解析并获取我们需要的数据了。
以 multipart/form-data 数据段格式的 POST 请求为拓展
有时需要向服务器后台上传图片、文件等类型的数据。这时,再使用 application/json 格式的数据段就行不通了。
下面介绍如何使用 multipart/form-data 格式的数据段进行文件数据的上传。
// 1. 创建 HTTP 请求对象
// 创建请求路径 - URL 的格式
NSURL *url=[NSURL URLWithString:@"http://172.18.176.202:3333/user/myName"];
// 创建 Request 对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// formdata 格式数据段特有要求,字段之间以及整个数据段结尾需要添加边界(BOUNDARY)
NSString *BOUNDARY = @"0xKhTmLbOuNdArY";
// 设置请求头(并设置我们用到的 BOUNDARY 的格式)
[request setValue:[@"multipart/form-data; boundary=" stringByAppendingString:BOUNDARY] forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"PATCH"];
// 设置请求的 body 部分(数据段)
NSMutableData *body = [NSMutableData data];
// param1 参数1
NSString *param1 = [NSString stringWithFormat:@"--%@\r\nContent-Disposition: form-data;name=\"%@\"\r\n\r\n%@\r\n",BOUNDARY,@"username",self.![textFieldA](https://img-blog.csdnimg.cn/20210414142852128.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzUzNjczNw==,size_16,color_FFFFFF,t_70)
.text,nil];
// 根据服务器接收数据的编码格式进行编码,此处使用 UTF-8 编码
[body appendData:[param1 dataUsingEncoding:NSUTF8StringEncoding]];
// param2 参数2,为一张图片,需要先将其转为 NSData 对象
NSData *data1 = UIImageJPEGRepresentation(self.avatar.image, 1.0);
NSString *param2 = [NSString stringWithFormat:@"--%@\r\nContent-Disposition: form-data; name=\"%@\";filename=\"%@\"\r\nContent-Type: application/octet-stream\r\n\r\n",BOUNDARY,@"avatar",[@"image-" stringByAppendingFormat:@"%@.png",self.textFieldA.text],nil];
[body appendData:[param2 dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:data1];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
//body结束分割线
NSString *endString = [NSString stringWithFormat:@"--%@--",BOUNDARY];
[body appendData:[endString dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody : body];
// 2. 发送 HTTP 请求
// 与前一部分一致,不再赘述
multipart/form-data 数据段格式 HTTP 请求示意图:
示意图中,请求的数据段部分包含两个数据:一个字段名为 “username” 的字符串类型数据,一个字段名为 “avatar” 的图片文件类型数据。
文件下载
使用 NSURLDownloadTask。
// 1. 直接使用文件资源的 URL 即可
// 创建请求路径 - URL 的格式
NSURL *url=[NSURL URLWithString:@"http://172.18.176.202:3333/download/test.txt"];
// 2. 发送 HTTP 请求
// 创建会话
NSURLSession *session=[NSURLSession sharedSession];
// 发起任务(Task)
NSURLDownloadTask*downloadTask=[session dataTaskWithURL:url completionHandler:^(NSURL*location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// location 为下载文件时,用户选择的希望文件保存的路径。如果为空,则存入默认的路径
// ...
}];
// 结束任务 !!!
[downloadTask resume];
文件上传
借助 multipart/form-data 数据段格式的 POST 请求,使用 NSURLSessionUploadTask。
// 本地文件路径
NSString * filePath = @"./text.txt";
// 1. 上传请求路径 - URL 的格式
NSURL *url=[NSURL URLWithString:@"http://172.18.176.202:3333/upload/test"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
[request setValue:[NSString stringWithFormat:@"multipart/form-data:boundary=%@", Kboundary] forHTTPHeaderField:@"Content-Type"];
// 2. 发送 HTTP 请求
// 创建会话
NSURLSession *session=[NSURLSession sharedSession];
// 发起任务(Task)
NSURLSessionUploadTask *uploadTask=[session dataTaskWithRequest:request fromData:[self getBodyData:filePath] completionHandler:^(NSURL*location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// ...
}];
// 结束任务 !!!
[uploadTask resume];
结语
记录 IOS Objective-C 如何使用 NSURLSession 进行 HTTP 请求。
仅供参考,敬请指正。