iPhone使用AFNetworking上传多部分文件

25

我在我的iOS应用程序中想要使用java API和NSMutableURLRequest发送multipart文件。这里是一个显示参数的表单。

  <form action="API_URL" encType='multipart/form-data' method=post>
            <input type=file name="files">
            <input type=submit value="Upload Attempt Files">

编辑form2

       <form action='URL' method="post" encType='multipart/form-data'>
<input name="key1" value='123'>
<input name="key2" value='asdf'>
<input name="key3" value='qwerty'>
<input name="key4" value='aaa'>
<input name="key5" value='aaa'>
<input name="key6" value='false'>
<input type="file"  name="files">
<input type=submit value="Create Forum Posts">
   </form>        

我该如何实现这一点?

这个问题展示了如何使用AFNetworking在iOS(objective c)中上传多部分文件。但是我不知道如何根据我正在使用的表单设置参数。


1
我是否正确地理解您想要通过Objective-C中的AFNetworking进行此上传?(提到“Java API”有些令人困惑,但我现在假设您只是说您正在服务器上运行一些Java。是这样吗?) - Rob
好的。iOS应用程序并不真正关心服务器在幕后使用什么技术,因为它是通过HTTP通信的,这是我们真正关心的。你问题中的“java”标签和参考可能会让读者走上错误的道路。你可能想要删除那些引用... - Rob
跟进问题:您的HTML有一个按钮,上面写着“上传尝试文件”,而您的file输入字段名为files(复数),但我假设您一次只上传一个文件。我的下面的答案是基于您发送一个文件的假设工作的,但如果在上面的HTML片段中省略了其他允许指定多个文件的内容(为了简洁起见),请告诉我。 - Rob
3个回答

86

查看您的HTML,<input type=file>namefiles,因此您需要将name参数设置为@"files",以便使用appendPartWithFileData方法。例如,使用AFNetworking 3.x

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

[manager POST:urlString parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    [formData appendPartWithFileData:imageData
                                name:@"files"
                            fileName:photoName mimeType:@"image/jpeg"];

    [formData appendPartWithFormData:[key1 dataUsingEncoding:NSUTF8StringEncoding]
                                name:@"key1"];

    [formData appendPartWithFormData:[key2 dataUsingEncoding:NSUTF8StringEncoding]
                                name:@"key2"];

    // etc.
} progress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
    NSLog(@"Response: %@", responseObject);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
    NSLog(@"Error: %@", error);
}];

(有关AFNetworking 1.x和2.x语法,请参阅本答案的修订历史记录。)


感谢您的帮助...这里是如何发送cookie数据进行身份验证...还有一件事,无论我发送什么请求,在服务器上都看不到,可能出了什么问题... - ios
@ios 不确定关于cookies,但也许这个答案可以帮助你。至于为什么它不起作用,我无法说,因为我在我的服务器上测试过,文件显示正常。但是如果您需要cookie数据进行身份验证并且尚未完成此操作,您是否期望它能够工作?无论如何,也许编辑您的问题,添加您上传代码的最新版本。 - Rob
@ios 我假设您只需在multipartFormRequestWithMethod块中添加对appendPartWithFormData:name的调用。 - Rob
我也尝试了这个 NSMutableData *val4key1 =[[NSMutableData alloc] init]; [val4key1 appendData:[[NSString stringWithFormat:@"%@",mystring] dataUsingEncoding:NSUTF8StringEncoding]; [formData appendPartWithFormData:val4key1 name:@"key1"]; 但它显示了“Invalid parameter not satisfying: body”错误,可能出了什么问题。 - ios
1
@ios 是的,从概念上讲,你可以简化为 [formData appendPartWithFormData:[mystring dataUsingEncoding:NSUTF8StringEncoding] name:@"key1"]; 请参考修订后的答案。我已经测试了上述代码,至少在我的服务器上是有效的。你在哪里看到这个错误? - Rob
@Rob 很棒的回答,你节省了我的时间,这个答案百分之百有效,只需记住在 API 或服务器中声明的变量名称,仅使用它来附加数据。继续保持!!! - Darshan Mothreja

5
-(void) makePhotoUploadRequest{

    NSArray *keys = [[NSArray alloc]initWithObjects:@"UserID", @"CompanyName" ,@"Location",@"Latitude",@"Longitude",@"Tagline",@"Goals",@"ColorName",nil];
    NSArray *values =[[NSArray alloc]initWithObjects:@"103",@"queppelin",@"Jaiur",@"11.3" ,@"12.3",@"Let's do it",@"Let's do it",@"Let's do it", nil];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];

    NSURL *baseUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@/%@/RegisterCompanyUser",serverRequest,serverPort,serverName]];

    NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
    [request setURL:baseUrl];
    [request setHTTPMethod:@"POST"];

   NSString *boundary = @"0xKhTmLbOuNdArY";
    NSString *endBoundary = [NSString stringWithFormat:@"\r\n--%@\r\n", boundary];

    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; charset=%@; boundary=%@", charset, boundary];
    [request addValue:contentType forHTTPHeaderField: @"Content-Type"];

    NSMutableData *tempPostData = [NSMutableData data];
    [tempPostData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];


           for(int i=0;i<keys.count;i++){
               NSString *str = values[i];
               NSString *key =keys[i];
               NSLog(@"Key Value pair: %@-%@",key,str);
               [tempPostData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
               [tempPostData appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
              // [tempPostData appendData:[@"\r\n--%@\r\n",boundary dataUsingEncoding:NSUTF8StringEncoding]];
                   [tempPostData appendData:[endBoundary dataUsingEncoding:NSUTF8StringEncoding]];

        }





    // Sample file to send as data
    [tempPostData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"Image\"; filename=\"%@\"\r\n", @"company-logo.png"] dataUsingEncoding:NSUTF8StringEncoding]];
    [tempPostData appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

    UIImage *myImageObj = [UIImage imageNamed:@"company-logo.png"];
    NSData *mydata= UIImagePNGRepresentation(myImageObj);
    NSLog(@"Image data:%d",mydata.length);
        [tempPostData appendData:mydata];

    [tempPostData appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [request setHTTPBody:tempPostData];

    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    if( theConnection )
    {
       dataWebService = [NSMutableData data] ;
        NSLog(@"request uploading successful");
    }
    else
    {
        NSLog(@"theConnection is NULL");
    }


}

0

您可以使用以下代码,利用afnetworking 3.x发送图像和任意数量的参数到multipart请求中:

 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
 //manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // uncomment this line when the server is not returning JSON

[manager POST: urlString parameters: nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    [formData appendPartWithFileData:imageData
                                name:@"file"
                            fileName:imageName mimeType:@"image/jpeg"];
        for (NSString *key in parameters) {
            [formData appendPartWithFormData:[[[parameters objectForKey:key] description] dataUsingEncoding:NSUTF8StringEncoding] name:key];
        }

    // etc.
} progress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
    NSLog(@"Response: %@", responseObject);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
    NSLog(@"Error: %@", error);
}];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接