【问题标题】:Post image and JSON data with one NSURLrequest使用一个 NSURLrequest 发布图像和 JSON 数据
【发布时间】:2013-09-19 03:49:49
【问题描述】:

我正在尝试将图像从客户端应用程序上传到我的 django 网络服务器。我正在尝试使用 NSURLConnection 创建与以下 curl 命令等效的命令。

curl -v  -S  -X POST  -H 'Accept: application/json' -F image=@"//Users/mackaiver/someImageOfACat.jpg;type=image/jpg"  -F kiosk="81" http://myurl.de/rest/image/ 

预期的响应是 HTTP 状态 201 Created 并且服务器确实期望某种我认为的 JSON 响应。当我使用这样的卷曲线时

curl -v  -S  -X POST  -H 'Accept: application/json' -F image=@"//Users/mackaiver/someImageOfACat.jpg;type=image/jpg" http://myurl.de/rest/image/

我希望得到 400 Bad Request 响应。到目前为止,一切都很好。这可以通过命令行上的 curl 正常工作。 现在我想在 iOS 中做到这一点。到目前为止,我认为我可以使用以下代码发送图像。

NSString *urlString = [ NSString stringWithFormat:@"%@image",REST_BASE_URL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"POST"];

NSData *imageData = UIImageJPEGRepresentation(image, 1.0);


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

NSMutableData *body = [NSMutableData data];

// file
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: attachment; name=\"image\"; filename=\"image_upload.jpg\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[NSData dataWithData:imageData]];
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

现在由于某种原因,这会产生 200 OK 响应,这完全不是我所期望的。另外我不知道如何添加 kiosk=81 参数。有没有办法做到这一点?我应该使用像 AFNetworking 这样的外部库吗?

提前致谢:)

编辑:

这就是我的代码现在的样子。查看 curl 命令和我的应用程序的 wireshark 输出,我似乎找不到任何差异。

NSString *urlString = [ NSString stringWithFormat:@"%@image",BASE_URL];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];


NSString *boundary = @"--6ee875e2289c9";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
NSString *accept = @"application/json";

[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
[request setValue:accept forHTTPHeaderField: @"Accept"];
[request setHTTPMethod:@"POST"];


NSMutableData *body = [NSMutableData data];

[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"image\"; filename=\"bla.jpg\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: image/jpg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[NSData dataWithData:imageData]];

[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"kiosk\"\r\n\r\n%@", kioskId] dataUsingEncoding:NSUTF8StringEncoding]];

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

[request setHTTPBody:body];
self.connection = [[NSURLConnection alloc]
                   initWithRequest:request
                   delegate:self];

【问题讨论】:

    标签: ios django json curl django-rest-framework


    【解决方案1】:

    您的 Django 网络服务需要 multipart/form-data 请求:

    • Accept: application/json 自定义标头字段,
    • imagekiosk 参数。

    您知道如何通过命令行使用 curl 来实现这一点,这要归功于以下选项:

    1. -H/--header <line> 设置您的自定义标题,
    2. -X POST 发出POST 请求,
    3. -F/--form <name=content> 指定多部分 POST 数据。

    在带有 NSURLConnectionNSURLRequest 的 Objective-C 中,您需要执行与上述选项等效的操作:

    1. 借助addValue:forHTTPHeaderField: 方法,您可以在NSURLRequest 实例上设置自定义标头,
    2. 您可以通过[request setHTTPMethod:@"POST"]; 执行POST 请求,
    3. 您需要使用[request setHTTPBody:body]; 设置格式正确的body 字符串。

    所以问题是:如何使用我的图像和信息亭参数手动创建多部分/表单数据正文字符串?

    RFCcurl --trace-ascii out.txt ... 可以帮助您构建主体(请注意,您需要 2 个边界部分,因为您有 2 个参数)。

    或者,您可以轻松找到许多有关如何执行此操作的示例,例如:Sending Multipart Forms with Objective-C

    最后,AFNetworking 是一个方便的 NSURLConnection 包装器。它特别方便,因为它提供了一个现成的 multipartFormRequestWithMethod 方法,用于执行多部分 POST 请求。所以你可以用它作为替代品。

    【讨论】:

    • 谢谢!恐怕我似乎无法让它发挥作用。我将 curl 命令的 wireshark 输出与我的应用程序的输出进行了比较。我无法分辨出任何差异。我更新了我的帖子以包含我最近的 ios 代码。也许我只是试试 AFNetworling 位。
    • 我使用了 link SO question 中描述的 AFNetworking 库。再次,wireshark 输出看起来类似于 curl 帖子。无论我发送什么数据,我仍然得到 200 OK 响应。我预计至少会有 400 个错误。
    • 我现在让它与 AFNetworking 一起工作 :D 猜我要切换整个应用程序以使用该库。再次感谢。
    • 那么带有 AFNetworking 的wireshark 输出呢?您应该参考AFStreamingMultipartFormData 实现并将其与您的代码进行比较以了解问题所在!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 2021-09-10
    • 2019-03-09
    • 2017-02-01
    • 1970-01-01
    相关资源
    最近更新 更多