NSURLSession访问网络数据

1.NSMutableURLRequest的设置

//创建NSMutableURLRequest对象

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

//设置请求类型

[request setHTTPMethod:@"POST"];

//设置超时时间

[request setTimeoutInterval:60];

//设置缓存策略

[request setCachePolicy:NSURLRequestReloadIgnoringCacheData];

//设置Base64认证

NSString *authString = [[[NSString stringWithFormat:@"%@:%@",kGlobal.userInfo.sAccount,kGlobal.userInfo.sPassword] dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
authString = [NSString stringWithFormat: @"Basic %@", authString];
[request setValue:authString forHTTPHeaderField:@"Authorization"];

//设置POST方法需要传递的参数

NSString *paramStr = [NSString stringWithFormat:@"PostID=%@&Name=%@&Text=%@",self.uuID,kGlobal.userInfo.sApplyName,self.textView.text];
NSData *bodyData = [paramStr dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:bodyData];

2.创建网络会话

//创建网络会话

NSURLSession *session = [NSURLSession sharedSession];

3.创建网络请求(本文介绍 NSURLSessionDataTask 和 NSURLSessionUploadTask 两种)

//方案一:使用NSURLSessionDataTask请求网络数据

NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error == nil) {
            NSLog(@"文字发布成功!");
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;//将response对象强制转换为NSHTTPURLResponse,可以获取HTTP响应报文的头信息,如响应代码200表示请求成功可以用(httpResponse.statusCode获取)
            NSLog(@"返回的Response:%@",httpResponse);
            NSError *error = nil;
       //而真正的HTTP响应的Body内容则需要序列化获取 NSDictionary
*dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];//返回一个字典类型数据
       //NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];//返回一个JSON数组
//NSArray *array = [NSJSONSerialization JSONObjectWithData:[[dic valueForKey:@"Pictures"] dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&error];//
[dic valueForKey:@"Pictures"]得到的是第一次解析得到的JSON Array的字符串,需要二次解析成JSON的数组      
if (!error) {
                NSLog(@"返回信息:%@",dic);
            }
        }else{
            NSLog(@"发布失败,代码%@",error);
        }
}];

4.发送网络请求

[task resume];

//方案二:使用NSURLSessionUploadTask请求网络数据,NSURLSessionUploadTask 和 NSURLSessionDataTask的不同之处在于NSURLSessionUploadTask更像Web的表单提交,例如模拟Web表单的图片上传可以使用NSURLSessionUploadTask。

NSURLSessionUploadTask *dataTask = [session uploadTaskWithRequest:request fromData:bodyData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {if (error == nil) {
            NSLog(@"发布成功!");
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            NSLog(@"statusCode:%lu",httpResponse.statusCode);
            NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
            
            if (picNum == self.imgsArray.count) {
                [SVProgressHUD showSuccessWithStatus:kTXT(@"IMUploadSuccess")];
                [self dismissViewControllerAnimated:YES completion:nil];
            }

        }else{
            NSLog(@"发布失败,代码%@!",error);
        }
}];

上面发送网络请求的方法和方法一的不同之处在于bodyData的构建,方法二的bodyData是模拟HTTP的报文结构来的,使用NSData来拼接HTTP报文。

//bodyData的构建方法

- (NSData *)getBodydataWithImage:(UIImage *)image
{
    //把文件转换为NSData
    NSData *fileData = UIImageJPEGRepresentation(image, 1.0);
    
    NSString *fileName=[Global getUniqueStrByUUID];
    
    //1.构造body string
    NSMutableString *bodyString = [[NSMutableString alloc] init];
    
    //2.拼接body string
    //(1)file_name
    [bodyString appendFormat:@"--%@
",boundry];
    [bodyString appendFormat:@"Content-Disposition: form-data; name="FileName"
"];
    [bodyString appendFormat:@"Content-Type: text/plain; charset="utf-8"

"];
    [bodyString appendFormat:@"aaa%@.jpg
",fileName];
    
    //(2)PostID
    [bodyString appendFormat:@"--%@
",boundry];
    [bodyString appendFormat:@"Content-Disposition: form-data; name="PostID"
"];
    [bodyString appendFormat:@"Content-Type: text/plain; charset="utf-8"

"];
    [bodyString appendFormat:@"%@
",self.uuID];
    
    //(3)pic
    [bodyString appendFormat:@"--%@
",boundry];
    [bodyString appendFormat:@"Content-Disposition: form-data; name="pic"; filename="%@.jpg"
",fileName];
    [bodyString appendFormat:@"Content-Type: image/jpeg

"];
    //[bodyString appendFormat:@"Content-Type: application/octet-stream

"];
    
    //3.string --> data
    NSMutableData *bodyData = [NSMutableData data];
    //拼接的过程
    //前面的bodyString, 其他参数
    [bodyData appendData:[bodyString dataUsingEncoding:NSUTF8StringEncoding]];
    //图片数据
    [bodyData appendData:fileData];
    
    //4.结束的分隔线
    NSString *endStr = [NSString stringWithFormat:@"
--%@--
",boundry];
    //拼接到bodyData最后面
    [bodyData appendData:[endStr dataUsingEncoding:NSUTF8StringEncoding]];
    
    return bodyData;
}

整个bodyData的构建过程原理根据HTTP报文上传图片时,格式用boundory进行分割,但是每次HTTP报文的boundory的值是不一样的,这里为了方便就定义一个固定值,其实固定值也是可以上传成功,亲测有效。HTTP的body体里面把文字和图片内容用boundory和换行符进行分割,分区发送,邮件内容也是类似,所以只要遵循HTTP报文的格式,就可以模拟HTTP报文上传图片。

//boundry的设置

static NSString *boundry = @"----------V2ymHFg03ehbqgZCaKO6jy";//设置边界

//[Global getUniqueStrByUUID]是工具类的方法,用于产生一个GUID,具体的方法明细如下:

+ (NSString *)getUniqueStrByUUID
{
    CFUUIDRef    uuidObj = CFUUIDCreate(nil);//create a new UUID
    
    //get the string representation of the UUID
    
    NSString    *uuidString = (__bridge_transfer NSString *)CFUUIDCreateString(nil, uuidObj);
    
    CFRelease(uuidObj);
    
    return uuidString ;
}

实例代码

原文地址:https://www.cnblogs.com/wobuyayi/p/6008978.html