AFNetworking 3.0中multipartFormRequestWithMethod丢失请求体及头部问题
我之前也碰到过类似的AFNetworking 3.x multipart上传丢失请求体的问题,结合你提到的排查点,给你几个经过验证的排查和修复方向:
1. 调整请求序列化的配置顺序
AFNetworking 3.x对请求序列化的顺序要求更严格,必须先设置所有参数、请求头,再构建multipart表单数据,反过来的话很容易导致参数被覆盖或者bodyStream没有正确整合内容。比如:
// 正确顺序示例 AFHTTPRequestSerializer *requestSerializer = [AFHTTPRequestSerializer serializer]; // 先设置普通请求参数、请求头 [requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"]; NSDictionary *params = @{@"userId": @"123", @"type": @"avatar"}; // 再构建multipart form data NSURLRequest *request = [requestSerializer multipartFormRequestWithMethod:@"POST" URLString:uploadURL parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { // 添加图片文件 [formData appendPartWithFileData:imageData name:@"file" fileName:@"avatar.jpg" mimeType:@"image/jpeg"]; } error:nil];
2. 禁止手动修改HTTPBody/HTTPBodyStream
你提到在AFURLRequestSerialization.m里执行[self.request setHTTPBodyStream:self.bodyStream]时内容存在,但要注意:AFNetworking 3.x会自动处理请求体的流构建,手动调用这个方法或者修改HTTPBody会干扰内部逻辑。
如果是你自己的代码里手动设置了这些属性,建议直接删掉;如果是AF内部代码执行的,那要排查是不是你的外部逻辑(比如请求拦截器)修改了request的属性,导致流内容被清空。
3. 开启调试日志定位问题
打开AF的日志开关,能看到完整的请求构建细节,确认参数和multipart分片是否被正确添加:
// 初始化序列化器后开启日志 requestSerializer.loggingEnabled = YES;
日志会打印请求的头部、multipart的每个part信息,如果某个参数或文件part没出现,就能快速定位是添加时的问题(比如文件数据为空、参数键名错误等)。
4. 检查NSURLSession配置是否干扰
AFNetworking 3.x基于NSURLSession,如果你自定义了NSURLSessionConfiguration,要注意:
- 不要手动设置
Content-Type请求头,AF会自动生成multipart/form-data; boundary=xxx,手动设置会导致服务器无法解析请求体; - 不要修改
HTTPMaximumConnectionsPerHost等可能影响流传输的参数(除非你明确知道后果)。
示例正确配置:
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:config];
5. 用最小化用例排除外部干扰
把上传代码抽成独立的测试用例,只保留核心逻辑:
NSData *testImageData = UIImagePNGRepresentation([UIImage imageNamed:@"test.png"]); AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer]; NSURLRequest *request = [serializer multipartFormRequestWithMethod:@"POST" URLString:@"https://your-upload-url.com" parameters:@{@"key":@"value"} constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { [formData appendPartWithFileData:testImageData name:@"uploadFile" fileName:@"test.png" mimeType:@"image/png"]; } error:nil]; AFURLSessionManager *manager = [AFURLSessionManager manager]; NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { if (error) { NSLog(@"Error: %@", error); } else { NSLog(@"Response: %@", responseObject); } }]; [uploadTask resume];
如果这个用例能正常工作,说明你的原有代码里有其他逻辑(比如全局请求拦截器、参数加密逻辑)干扰了请求构建。
内容的提问来源于stack exchange,提问作者bugman

