使用 ASIHTTPRequest 将文件上传到 django-piston
我正在尝试使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我基本上已经解决了这个问题。
基本问题是 Django 期望将文件提交到服务器的请求格式是 django-piston 字面意义上的错误格式。
当它遇到多部分请求时,它根本不会尝试解析数据。
这个问题的解决方案是手动调用解析引擎,在 JSON 的情况下,它是直接从 django.utils 中调用的(这有点令人失望)。
您可以通过使用 ASIHTTPRequest(或您选择的请求模块)按键设置标准发布值,然后以老式方式访问它来实现此目的。
就您必须采取的步骤而言,这基本上只是将此时的处理程序方法简化为普通的旧 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.
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?
那是行不通的,不。如果您使用“application/x-www-form-urlencoded”格式或“multipart/form-data”发布表单数据,您将无法在末尾添加一些额外的数据 - 它需要作为表单数据的一部分输入。我猜是这样的......
[request setPostValue:@"{\"save\":{\"name\":\"iostest\"}}" forKey:@"data"];
问题比较多...
我可能不会首先朝那个方向看 - 活塞并没有真正干扰请求对象,因此 ASI 请求似乎不太正确。
我认为首先要检查传入的请求并检查它是否确实是有效的表单
POST
请求:request["CONTENT_TYPE"]
是否设置为'multipart/form-data'request.raw_post_data
并确保它是 http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 - 检查键名称如您所料,并且文件内容存在。 (显然,在测试时您需要使用一个小文本文件!)request.FILES
中实际存在哪些键(如果有),以防它像字段名称错误。如果这一切都失败了,我会尝试通过尝试编写一个简单的 python 客户端并查看是否有相同的问题来缩小客户端或服务器端的问题范围。环顾四周,像这样的东西: http://atlee.ca/software/poster/ 可能有用。
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"];
Is more problematic...
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 form
POST
request:request["CONTENT_TYPE"]
is set to 'multipart/form-data'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!)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.