最近项目服务器由Windows平台迁移到Linux平台后,发现苹果IOS客户端POST提交数据为空,无法上传视频,但是同样的接口,安卓客户端正常。以下是整个问题的排查过程。
首先确认IOS端上传插件是否用AF或AFN。参考下面方法解决。
可能导致该问题的原因一:缺少请求头。
我们知道在普通网页Form表单提交数据时,需要给表单添加enctype ="multipart/form-data",同样苹果IOS端POST上传文件也需要请求头。
- manager.requestSerializer setValue:@"text/xml;charset=utf-8" forHTTPHeaderField:@"Content-Type"
可能导致该问题的原因二:返回JSON格式错误。
通过AF提交数据已经做过解析,此时需要检查后台返回JSON格式是否有误,如果JSON格式不规范,可以协商后台进行修改。
可能导致该问题的原因三:数据协议不正确。
导致该问题出现的原因很可能是服务器采用了数据加密传输,如:https。此时可检查http上传文件是否正常,如果http上传文件正常,那么协商服务器给客户端cer证书。
附修改过AFN上传插件https提交数据单例源码。
- + (AFHTTPSessionManager *)sharedAFManager
- {
- static AFHTTPSessionManager *manager = nil;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- manager = [AFHTTPSessionManager manager];
- /*! 设置请求超时时间 */
- manager.requestSerializer.timeoutInterval = 30;
- /*! 打开状态栏的等待菊花 */
- [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
- /*! 设置相应的缓存策略:此处选择不用加载也可以使用自动缓存【注:只有get方法才能用此缓存策略,NSURLRequestReturnCacheDataDontLoad】 */
- manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
- /*! 设置返回数据类型为 json, 分别设置请求以及相应的序列化器 */
- /*!
- 根据服务器的设定不同还可以设置:
- json:[AFJSONResponseSerializer serializer](常用)
- http:[AFHTTPResponseSerializer serializer]
- */
- AFJSONResponseSerializer *response = [AFJSONResponseSerializer serializer];
- /*! 这里是去掉了键值对里空对象的键值 */
- response.removesKeysWithNullValues = YES;
- manager.responseSerializer = response;
- /* 设置请求服务器数类型式为 json */
- /*! 根据服务器的设定不同还可以设置 [AFJSONRequestSerializer serializer](常用) */
- AFJSONRequestSerializer *request = [AFJSONRequestSerializer serializer];
- manager.requestSerializer = request;
- /*! 设置apikey ------类似于自己应用中的tokken---此处仅仅作为测试使用*/
- // [manager.requestSerializer setValue:apikey forHTTPHeaderField:@"apikey"];
- /*! 复杂的参数类型 需要使用json传值-设置请求内容的类型*/
- // [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
- /*! 设置响应数据的基本类型 */
- manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/css",@"text/xml",@"text/plain", @"application/javascript", @"image/*", nil];
- /*! https 参数配置 */
- /*!
- 采用默认的defaultPolicy就可以了. AFN默认的securityPolicy就是它, 不必另写代码. AFSecurityPolicy类中会调用苹果security.framework的机制去自行验证本次请求服务端放回的证书是否是经过正规签名.
- */
- AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
- securityPolicy.allowInvalidCertificates = YES;
- securityPolicy.validatesDomainName = NO;
- manager.securityPolicy = securityPolicy;
- /*! 自定义的CA证书配置如下: */
- /*! 自定义security policy, 先前确保你的自定义CA证书已放入工程Bundle */
- /*!
- https://api.github.com网址的证书实际上是正规CADigiCert签发的, 这里把Charles的CA根证书导入系统并设为信任后, 把Charles设为该网址的SSL Proxy (相当于"中间人"), 这样通过代理访问服务器返回将是由Charles伪CA签发的证书.
- */
- // NSSet <NSData *> *cerSet = [AFSecurityPolicy certificatesInBundle:[NSBundle mainBundle]];
- // AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:cerSet];
- // policy.allowInvalidCertificates = YES;
- // manager.securityPolicy = policy;
- /*! 如果服务端使用的是正规CA签发的证书, 那么以下几行就可去掉: */
- // NSSet <NSData *> *cerSet = [AFSecurityPolicy certificatesInBundle:[NSBundle mainBundle]];
- // AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:cerSet];
- // policy.allowInvalidCertificates = YES;
- // manager.securityPolicy = policy;
- /*post 请求 服务器端接收数据为空 是因为要初始化下面这个方法*/
- manager.requestSerializer = [AFHTTPRequestSerializer serializer];
- });
- return manager;
- }
在POST数据时进行方法初始化。
- manager.requestSerializer = [AFHTTPRequestSerializer serializer];
因为波波本身不是做IOS开发的,所以在此特别向提供解决方案的春蕾兄弟表示感谢。