使用 ASIHTTPRequest 将文件上传到 django-piston

发布于 2024-10-17 23:41:04 字数 1326 浏览 2 评论 0原文

我正在尝试使用 ASIHTTPRequest 将一些 JSON 和一个二进制文件从 iPhone 发布到运行 django-piston 的 Django 服务器,

如果我只发送 JSON 字符串,我知道如何让它工作,并且我知道如何让它工作,如果我只发送一个文件,但同时发送两个文件很棘手。

因此,我们将从 ASIHTTPRequest 代码开始。

ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:url];

[request setRequestMethod:@"POST"];

[request setPostFormat:ASIMultipartFormDataPostFormat];

[request appendPostData:[@"{\"save\":{\"name\":\"iostest\"}}" dataUsingEncoding:NSUTF8StringEncoding]];

[request addData:UIImageJPEGRepresentation([UIImage imageNamed:@"test.jpg"], 1.0f)
    withFileName:@"test.jpg"
  andContentType:@"image/jpeg"
          forKey:@"data"];

[request setDelegate:self];

[request startAsynchronous];

我的最佳想法是,将原始字符串数据直接添加到 POST 正文,然后添加文件是行不通的。

但如果我尝试

[request setPostValue:@"{\"name\":\"iostest\"}" forKey:@"save"];

那么活塞数据字典会将 ['save'] 存储为字符串而不是反序列化的对象,因此它会逐字传递字符串

"{\"name\":\"iostest\"}"

这是我的活塞处理程序代码

def create(self, request):

     data = request.data

     print(data['save']) #{\"name\":\"iostest\"}"
     print("Files: " + request.FILES['data'].name) #test.jpg
     print("Data Save Name: " + data['save']['name']) #crash, interprets this as a string indeces lookup

欢迎提出想法。

I'm trying to POST some JSON and a binary file from an iPhone to a Django server running django-piston using ASIHTTPRequest

I know how to get it to work if I am ONLY sending JSON strings, and I know how to make it work if I am ONLY sending a file, but doing both is tricky.

So we'll start with ASIHTTPRequest code

ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:url];

[request setRequestMethod:@"POST"];

[request setPostFormat:ASIMultipartFormDataPostFormat];

[request appendPostData:[@"{\"save\":{\"name\":\"iostest\"}}" dataUsingEncoding:NSUTF8StringEncoding]];

[request addData:UIImageJPEGRepresentation([UIImage imageNamed:@"test.jpg"], 1.0f)
    withFileName:@"test.jpg"
  andContentType:@"image/jpeg"
          forKey:@"data"];

[request setDelegate:self];

[request startAsynchronous];

My best idea here is that adding raw string data directly to the POST body and then adding a file just doesn't work.

But if I instead try

[request setPostValue:@"{\"name\":\"iostest\"}" forKey:@"save"];

Then the piston data dictionary will store ['save'] as a string instead of a deserialized object, so it will literally deliver the string

"{\"name\":\"iostest\"}"

Here's my Piston handler code

def create(self, request):

     data = request.data

     print(data['save']) #{\"name\":\"iostest\"}"
     print("Files: " + request.FILES['data'].name) #test.jpg
     print("Data Save Name: " + data['save']['name']) #crash, interprets this as a string indeces lookup

Ideas are welcome.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

秉烛思 2024-10-24 23:41:04

我基本上已经解决了这个问题。

基本问题是 Django 期望将文件提交到服务器的请求格式是 django-piston 字面意义上的错误格式。

当它遇到多部分请求时,它根本不会尝试解析数据。

这个问题的解决方案是手动调用解析引擎,在 JSON 的情况下,它是直接从 django.utils 中调用的(这有点令人失望)。

您可以通过使用 ASIHTTPRequest(或您选择的请求模块)按键设置标准发布值,然后以老式方式访问它来实现此目的。

from django.utils import simplejson
data = simplejson.loads(request.POST['save'])

就您必须采取的步骤而言,这基本上只是将此时的处理程序方法简化为普通的旧 Django 视图。

很明显,django-piston 显然不是为了处理文件而构建的?

I have basically hacked my way around this.

The basic problem is that the request format in which Django expects files to be submitted to the server is one which django-piston literally just drops the ball on.

When it encounters multipart requests, it simply doesn't try to parse the data.

The solution to this problem is to manually call the parsing engine, which, in the case of JSON, is straight out of django.utils (which is kind of disappointing).

You achieve this by using ASIHTTPRequest (or the request module of your choice) to set a standard post value by key, and then access it the old fashioned way.

from django.utils import simplejson
data = simplejson.loads(request.POST['save'])

Which basically just reduces this handler method at this point to nothing more than a regular old Django view in terms of the steps you have to take to get it going.

So clearly, django-piston is not built to deal with files apparently?

绳情 2024-10-24 23:41:04

我最好的想法是添加原始数据
字符串数据直接发送到 POST 正文
然后添加一个文件却没有
工作。

那是行不通的,不。如果您使用“application/x-www-form-urlencoded”格式或“multipart/form-data”发布表单数据,您将无法在末尾添加一些额外的数据 - 它需要作为表单数据的一部分输入。我猜是这样的......

[request setPostValue:@"{\"save\":{\"name\":\"iostest\"}}" forKey:@"data"];

但是如果我删除字符串数据并仅发布文件,它仍然不起作用。

问题比较多...

或者活塞是否错误地误读了数据。

我可能不会首先朝那个方向看 - 活塞并没有真正干扰请求对象,因此 ASI 请求似乎不太正确。

我认为首先要检查传入的请求并检查它是否确实是有效的表单POST请求:

  1. 检查request["CONTENT_TYPE"]是否设置为'multipart/form-data'
  2. 检查 request.raw_post_data 并确保它是 http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 - 检查键名称如您所料,并且文件内容存在。 (显然,在测试时您需要使用一个小文本文件!)
  3. 检查 request.FILES 中实际存在哪些键(如果有),以防它像字段名称错误。

如果这一切都失败了,我会尝试通过尝试编写一个简单的 python 客户端并查看是否有相同的问题来缩小客户端或服务器端的问题范围。环顾四周,像这样的东西: http://atlee.ca/software/poster/ 可能有用。

My best idea here is that adding raw
string data directly to the POST body
and then adding a file just doesn't
work.

That wouldn't work, no. If you're POSTing form data using 'application/x-www-form-urlencoded' format, or 'multipart/form-data' you're not going to be able to just tack some extra data on the end - it needs to go in as part of the form data. Something like this I guess...

[request setPostValue:@"{\"save\":{\"name\":\"iostest\"}}" forKey:@"data"];

But if I remove the string data and only post the file it still doesn't work.

Is more problematic...

or if it's Piston erroneously misreading the data.

I probably wouldn't look in that direction first - piston doesn't really mess with the request object, so it seems more likely that the ASI request isn't quite right.

I think the place to start would be to inspect the incoming request and check that it really is a valid formPOST request:

  1. Check that request["CONTENT_TYPE"] is set to 'multipart/form-data'
  2. Inspect the request.raw_post_data and make sure that it is valid form data as specified in http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 - check that the key names are as you expected and that the file content is present. (Obviously you'll want to use a small text file when you're testing this!)
  3. Check which keys actually are present in request.FILES, if any, in case it's as simple as something like a misnamed field.

Failing all that I'd try to narrow down if it's a problem on the client or server side by trying to write a plain python client and seeing if you have the same issue then. Looking around, something like this: http://atlee.ca/software/poster/ might be useful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文