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的主要内容,如果未能解决你的问题,请参考以下文章

使用 AFNetworking 的多部分 PUT 请求

使用 json 数据和使用 afnetworking 的多部分请求

AFNetworking https 请求不起作用

AFNetworking GET 正文中的参数

oauth1 中的多租户身份验证问题

AFNetworking GET 参数与包含在 URL 键参数中的 JSON (NSDictionary) 字符串