AFNetworking V2.0 中的多参数 POST
Posted
技术标签:
【中文标题】AFNetworking V2.0 中的多参数 POST【英文标题】:POST with multiple parameters in AFNetworking V2.0 【发布时间】:2013-11-04 10:42:17 【问题描述】:我正在将一些(相当旧的)ASIHTTPRequest 代码更新到 AFNetworking V2.0。
现在我正在处理一个 POST 请求,该请求上传一个带有额外参数的 NSDictionary。
ASIHTTPRequest 代码如下所示:
NSMutableData* mPostData = [NSMutableData dataWithData:[postData dataUsingEncoding:NSUTF8StringEncoding]];
NSString *msgLength = [NSString stringWithFormat:@"%d", [postData length]];
[r setPostBody: mPostData];
[r addRequestHeader: @"Content-Length" value:msgLength];
postData 是一个具有键/值的 NSDictionary - 它基于所采取的操作。例如 - 上传图片会有额外的参数。完成用户注册将有不同的参数 - 但使用与此代码相同的方法。
委托调用这段代码:
//Request must be ASIFormDataRequest
- (BOOL) addFileWithPath:(NSString*) filePath fileName: (NSString*)fileName ofType: (NSString*) fileType withKey: (NSString*) fileKey uploadProgressDelegate:(id) uploadProgressDelegate
if ([request isKindOfClass:[ASIFormDataRequest class]])
ASIFormDataRequest *formRequest = (ASIFormDataRequest *) request;
NSLog(@"%@ %@ %@ %@",filePath,fileName,fileType,fileKey);
if (uploadProgressDelegate)
[formRequest setUploadProgressDelegate:uploadProgressDelegate];
NSLog(@"filename = %@",fileName);
[formRequest setFile:filePath withFileName:fileName andContentType:fileType forKey:fileKey];
return YES;
else
NSLog(@"WebService must be initialised with PostDataValuesAndKeys so that ASIFormDataRequest is made");
return NO;
现在从我已经完成的挖掘量来看 - 我只能看到这段 AfNwtworking
代码 - 在我看来它就像来自版本 1.x
NSString *urlString = @"yourUrl";
NSURL* url = [NSURL URLWithString:urlString];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSURL *localVideoURL = [NSURL URLWithString:[userDefaults objectForKey:@"videoURL"]];
NSData *videoData = [NSData dataWithContentsOfURL:localVideoURL];
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:@"POST" path:nil parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData)
[formData appendPartWithFileData:videoData name:@"video_file" fileName:@"testvideo.mov" mimeType:@"video/quicktime"];
[formData appendPartWithFormData:[[BAUserInfoParser userInfoJson] dataUsingEncoding:NSUTF8StringEncoding] name:@"userInfo"];
[formData appendPartWithFormData:[[userDefaults objectForKey:@"transactionReceiptData"] dataUsingEncoding:NSUTF8StringEncoding] name:@"transactionData"];
];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite)
// NSLog(@"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
float uploadPercentge = (float)totalBytesWritten / (float)totalBytesExpectedToWrite;
float uploadActualPercentage = uploadPercentge *100;
[lblUploadInfoText setText:[NSString stringWithFormat:@"%.2f %%",uploadActualPercentage]];
if (uploadActualPercentage >= 100)
lblStatus.text = @"Waitting for response ...";
progressBar.progress = uploadPercentge;
];
[httpClient enqueueHTTPRequestOperation:operation];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
lblStatus.text = @"Upload Complete";
NSData *JSONData = [operation.responseString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:JSONData options:NSJSONReadingMutableContainers error:nil];
failure:^(AFHTTPRequestOperation *operation, NSError *error)
NSLog(@"error: %@", operation.responseString);
NSLog(@"%@",error);
];
[operation start];
在AFNetworking
的第 2 版中 - 有一些新的便利方法可以解决此类问题:
这是带有额外块的 POST 方法..
[self.manager POST:url parameters:urlParameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
// postData
success:^(NSURLSessionDataTask *task, id responseObject)
//Success
failure:^(NSURLSessionDataTask *task, NSError *error)
//Failure
];
但是它的constructingBodyWithBlock 我遇到了问题。我不确定我需要做什么才能获取 NSDictionary 对象并将其上传到该块中。
【问题讨论】:
对于 POST 请求的正文数据,您需要什么 Content-Type?注意:AFN 将在方便的 POST 方法中使用“application/x-www-form-urlencoded”。这与您在 ASIFormDataRequest 中使用的不同。 @CouchDeveloper 内容类型需要与我在 ASIFormDataRequest 中使用的相同。 OK,那就试试POST方便的方法。将您的参数作为字典放入 parameters 参数中。这将成为多部分消息的第一部分,其内容类型为“application/x-www-form-urlencoded”。第二部分将成为您在块中实现的任何内容。沿着这个[formData appendPartWithFileURL:filePath name:@"image" error:nil];
的东西会添加一个文件。该部分的 Content-Type 将自动确定。
好吧,我虽然你有一组参数和一个文件,正如你在旧代码中显示的那样。这是需要放入 HTTP 消息正文的两个部分。因此,您需要一个“多部分消息”。如果您只有一组参数,则(严格)不需要多部分消息。内容类型为“application/x-www-form-urlencoded”的 HTTP 消息就足够了。在这种情况下,您的参数将被编码并构成正文。更好的是,您可以使用内容类型“application/json”将一组参数作为 JSON 传递。检查 Web 服务可以接受的内容。 :)
是的,完全正确。上传文件通常使用多部分消息完成。出于历史原因,请参阅:RFC 1867 和 RFC 2854,以及网络中的各种资源。
【参考方案1】:
urlParameters 应该是一个 NS 字典。因为它是一个正在上传的对象
NSDictionary *urlParameters(制作你的字典)
参数:url参数
这对我有用。
【讨论】:
谢谢。我正确地提出了发布请求,并且确实使用 NSDiconary 来处理此类请求。以上是关于AFNetworking V2.0 中的多参数 POST的主要内容,如果未能解决你的问题,请参考以下文章