我试图使用Python的Requests库向amazons3端点发送请求。该请求属于multipart/form数据类型,因为它包含实际文件的过账。在
我正在处理的API指定的一个要求是file
参数必须最后一次发布到上。由于请求使用字典来发布多部分/表单数据,并且由于字典不遵循指定的顺序,所以我将其转换为称为payload
的OrderedDict。发布前它看起来像这样:
{'content-type': 'text/plain',
'success_action_redirect': 'https://ian.test.instructure.com/api/v1/files/30652543/create_success?uuid=<opaque_string>',
'Signature': '<opaque_string>',
'Filename': '',
'acl': 'private',
'Policy': '<opaque_string>',
'key': 'account_95298/attachments/30652543/log.txt',
'AWSAccessKeyId': '<opaque_string>',
'file': '@log.txt'}
我是这样贴出来的:
^{pr2}$回答是500个错误,所以我真的不确定问题出在这里。我只是猜测这与我在请求中使用OrderedDict有关—我找不到任何文档表明请求支持或不支持OrderedDict。可能会完全不同。在
是否还有其他会导致请求失败的突出问题?如果需要,我可以提供更多细节。在
好的,根据Martijn Pieters之前的评论进行更新:
我改变了我引用日志.txt将其添加到已创建的upload_data
字典中,如下所示:
upload_data['file'] = open("log.txt")
pprinting得到的字典如下:
{'AWSAccessKeyId': '<opaque_string>',
'key': '<opaque_string>',
'Policy': '<opaque_string>',
'content-type': 'text/plain',
'success_action_redirect': 'https://ian.test.instructure.com/api/v1/files/30652688/create_success?uuid=<opaque_string>',
'Signature': '<opaque_string>',
'acl': 'private',
'Filename': '',
'file': <_io.TextIOWrapper name='log.txt' mode='r' encoding='UTF-8'>}
file
键的值是否正确?在
当我把它发布到一个RequestBin时,我得到了这样一个结果,它看起来很像Martin的例子:
POST /1j92n011 HTTP/1.1
User-Agent: python-requests/1.1.0 CPython/3.3.0 Darwin/12.2.0
Host: requestb.in
Content-Type: multipart/form-data; boundary=e8c3c3c5bb9440d1ba0a5fe11956e28d
Content-Length: 2182
Connection: close
Accept-Encoding: identity, gzip, deflate, compress
Accept: */*
--e8c3c3c5bb9440d1ba0a5fe11956e28d
Content-Disposition: form-data; name="AWSAccessKeyId"; filename="AWSAccessKeyId"
Content-Type: application/octet-stream
<opaque_string>
--e8c3c3c5bb9440d1ba0a5fe11956e28d
Content-Disposition: form-data; name="key"; filename="key"
Content-Type: application/octet-stream
<opaque_string>
--e8c3c3c5bb9440d1ba0a5fe11956e28d
Content-Disposition: form-data; name="Policy"; filename="Policy"
Content-Type: application/octet-stream
<opaque_string>
--e8c3c3c5bb9440d1ba0a5fe11956e28d
Content-Disposition: form-data; name="content-type"; filename="content-type"
Content-Type: application/octet-stream
text/plain
--e8c3c3c5bb9440d1ba0a5fe11956e28d
Content-Disposition: form-data; name="success_action_redirect"; filename="success_action_redirect"
Content-Type: application/octet-stream
https://ian.test.instructure.com/api/v1/files/30652688/create_success?uuid=<opaque_string>
--e8c3c3c5bb9440d1ba0a5fe11956e28d
Content-Disposition: form-data; name="Signature"; filename="Signature"
Content-Type: application/octet-stream
<opaque_string>
--e8c3c3c5bb9440d1ba0a5fe11956e28d
Content-Disposition: form-data; name="acl"; filename="acl"
Content-Type: application/octet-stream
private
--e8c3c3c5bb9440d1ba0a5fe11956e28d
Content-Disposition: form-data; name="Filename"; filename="Filename"
Content-Type: application/octet-stream
--e8c3c3c5bb9440d1ba0a5fe11956e28d
Content-Disposition: form-data; name="file"; filename="log.txt"
Content-Type: text/plain
This is my awesome test file.
--e8c3c3c5bb9440d1ba0a5fe11956e28d--
但是,当我尝试将其发布到https://instructure-uploads.s3.amazonaws.com/时,仍然会返回500。我尝试过将open file对象添加到files
中,然后通过data
在单独的dict中提交所有其他值,但这也不起作用。在
您可以传入一个
dict
、或两个值元组的序列。在并且
OrderedDict
被简单地转换成这样一个序列:但是,由于
collections.OrderedDict()
类型是dict
的子类,调用items()
实际上是requests
在幕后的作用,所以直接传递OrderedDict
实例也同样有效。在因此,有些事情是错误的。您可以通过发布到
^{pr2}$http://httpbin/post
来验证正在发布的内容:不幸的是,
httpbin.org
没有保持顺序。或者,您也可以在http://requestb.in/创建一个专用的httppostbin;它将更详细地告诉您发生了什么。在使用请求B.in,通过将
'@log.txt'
替换为打开的文件对象,POST from请求被记录为:显示顺序正确保留。在
请注意,
requests
不支持特定于Curl的@filename
语法;而是传入一个open file对象:您可能还想设置
content-type
字段以使用标题大小写:'Content-Type': ..
。在如果您仍然得到500个响应,请检查
r.text
响应文本,看看Amazon认为什么是错误的。在您需要将发送的内容拆分为传递给
data
的OrderedDict和发送给files
的OrderedDict。现在,AWS(正确地)将数据参数解释为文件,而不是表单参数。应该是这样的:相关问题 更多 >
编程相关推荐