最新消息:iOS编程开发交流群(6906921) ,Mac.Cocoa开发交流群(7758675) 欢迎iOS/macOS开发编程爱好及学习者加入!

iOS网络请求AFNetworking "Request failed: unacceptable content-type: text/html"

iOS 天狐 23671浏览 0评论

科普 ContentType

Content-Type,内容类型,一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件与内容,这就是经常看到一些网页点击的结果却是下载到的一个文件或一张图片的原因。

比如使用火狐浏览器打开网址:http://api.skyfox.org/project/afndemo/newsList.do ,右键查看页面信息。类型即ContentType

eff8f058-c668-4deb-b56f-ad5d6b56d44a

requestSerializer与responseSerializer

10d3052c-8c04-4041-97b3-940f718da427

requestSerializer

简单的来说AFNetworking的requestSerializer是决定AFNetworking以何种方式格式化序列化数据(即parameters,我们通常传一个字典)去请求api。

最终后台接收到的并不是我们认为的iOS中的一个字典parameters,或一个数组parameters

AFNetworking框架自动的将其格式化序列化成JSON、XML、等等文本格式,编码后放到HTTP请求的Body中,最后由后台API接收到。

请求的数据编码格式

而AFNetworking请求的数据编码格式又以下几种:

AFHTTPRequestSerializer      二进制

AFJSONRequestSerializer    JSON

AFPropertyListRequestSerializer   Plist

responseSerializer

简单的来说AFNetworking的responseSerializer是决定以何种方式格式化后台API响应返回的数据。

理论上完整的HTTP响应结束后,AFNetworking收到的并不是一个字典responseObject,或一个数组responseObject对象。而是字符串或者二进制数据。

AFNetworking框架自动的将HTTP响应回来的字符串数据(JSON、XML、二进制),反序列化解析成了APP端的对象,最终反回了responseObject对象。

响应的数据解码格式

AFHTTPResponseSerializer               二进制

AFJSONResponseSerializer              JSON

AFPropertyListResponseSerializer    Plist

AFXMLParserResponseSerializer      XML

AFImageResponseSerializer             Image

AFCompoundResponseSerializer      组合的

unacceptable content-type

com.alamofire.serialization.response.error.data=<5b7b2273 74617475 73223a22 73756363 65737322 2c226d73 67223a22 e799bbe9 9986e688 90e58a9f 227d5d>, NSLocalizedDescription=Request failed: unacceptable content-type: text/html}

AFNetworking请求API遇到这个问题的原因是,HTTP响应头中的 Content-Type 与返回数据的格式不一致导致的

比如常常后台API认为返回的是JSON编码的数据,虽然看似是JSON格式没错,但其实Content-Type并不是对应的JSON类型,这会导致客户端,即AFNetworking认为返回的数据是无效的数据,从而报错。

一个方法就是后台webservice更改返回数据的Content-Type为正确的application/json和text/json

如果后端某些原因无法更改,iOS客户端可以强制把未识别的 text/html类型加到AFNetworking可识别的列表中:

//_sharedClient为AFHTTPRequestOperationManager或者AFHTTPSessionManager的实例对象
_sharedClient.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html", @"text/plain",nil];

acceptableContentTypes 为NSSet,如果缺后台对应的Content-type,可以直接添加进去

或者用更稳妥的方法,原有基础上追加Content-type

_sharedClient.responseSerializer.acceptableContentTypes =  [_sharedClient.responseSerializer.acceptableContentTypes setByAddingObjectsFromSet:[NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html", @"text/plain",@"application/atom+xml",@"application/xml",@"text/xml",@"image/png",@"image/jpeg",nil]];

一个完整AFNetworking示例

+ (NSURLSessionDataTask *)X_POST:(NSString *)URLString
                        parameters:(id)parameters
                           success:(void (^)(id responseObject))success
                           failure:(void (^)(NSError *error))failure{
    AFHTTPSessionManager *manager =  [AFHTTPSessionManager manager];
    //发送json数据  {"key":"value","key2":"value2"}
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    //响应json数据
    manager.responseSerializer  = [AFJSONResponseSerializer serializer];
    
    ////发送二进制form数据 key=value&key2=value2
    //manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    ////响应二进制form数据
    //manager.responseSerializer  = [AFHTTPResponseSerializer serializer];
    
    //直接发送JSON给服务器端   对应[AFJSONRequestSerializer serializer];
    //实际httpbody中的数据为 {"name":"sky","password":"fox"}
    NSDictionary *parametersDemo = @{@"name":@"sky",@"password":@"fox"};
    
    ////将请求参数转换为JSON后放入key为aJSON的字典中发送请求    对应[AFHTTPRequestSerializer serializer];
    ////实际httpbody中的数据为  {"aJSON":"{"name":"sky","password":"fox"}","key":"value"}
    // NSDictionary *parametersJSON = @{@"name":@"sky",@"password":@"fox"};
    //NSData *JSONData = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:nil];
    //NSString *JSONString = [[NSString alloc] initWithData:parametersJSON encoding:NSUTF8StringEncoding];
    //NSMutableDictionary *parametersDemo = @{@"aJSON":JSONString?:@"",@"key":@"value"};
   
    
    manager.responseSerializer.acceptableContentTypes =  [manager.responseSerializer.acceptableContentTypes setByAddingObjectsFromSet:[NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html", @"text/plain",@"application/atom+xml",@"application/xml",@"text/xml",nil]];
    return  [manager POST:URLString parameters:parametersDemo progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        success(responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSString *responseString =  [[NSString alloc] initWithData:(NSData *)error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] encoding:NSUTF8StringEncoding];
        NSLog(@"%@",responseString);
        failure(error);
    }];
}

所有的ContentTypes都包含在http://www.iana.org/assignments/media-types/media-types.xhtml中

转载请注明:天狐博客 » iOS网络请求AFNetworking "Request failed: unacceptable content-type: text/html"

微信 OR 支付宝 扫描二维码
为天狐 打赏
非常感谢你的支持,哥会继续努力!
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址