【问题标题】:Uploading files to django-piston with ASIHTTPRequest使用 ASIHTTPRequest 将文件上传到 django-piston
【发布时间】:2011-02-19 18:18:31
【问题描述】:

我正在尝试使用 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

欢迎提出想法。

【问题讨论】:

    标签: django asihttprequest django-piston


    【解决方案1】:

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

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

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

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

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

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

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

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

    【讨论】:

    • 我认为您对那里的活塞有点苛刻;-) 您所做的并不是很常见的模式。如果您在表单 POST 请求中上传文件,最好也提供任何其他数据作为表单数据。当我在回复中提到将 JSON 数据添加到表单字段时,我有点慢 - 这样做更有意义:[request setPostValue:@"iostest" forKey:@"name"]跨度>
    • 它会,但是当您通常花时间编写将所有对象序列化为 JSON 的 iOS 代码时,不得不为一两个请求中断格式,这令人不安。
    【解决方案2】:

    我最好的想法是添加原始 将字符串数据直接发送到 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/ 可能有用。

    【讨论】:

    • 我尝试遍历密钥文件 FILES 但它似乎不喜欢该对象上的 .keys() 。什么是迭代 FILES 键的好方法? -- 一旦我能回到那个项目,我会检查另外两个。
    • 好的。所以主要问题 #1 是 ASIHTTPRequest 对文件默默地失败了,因为文件路径有点不正确,这要归功于 Cocoa 的某些部分吸吮。所以,我现在处于 Piston 正在读取和接受上传文件的地方,但现在最大的谜团是如何以 Piston 可以接受的方式组合文件发布和数据发布。 ASI 的 setPostValue 方法只是使它以带有 Piston 的字符串结束。所以活塞中的 data['data'] 只是一个字符串,而不是 JSON 对象。现在将更新主要问题。
    猜你喜欢
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    • 2017-08-18
    • 2012-03-20
    • 2018-06-08
    相关资源
    最近更新 更多