python:具有未编码二进制数据的HTTP PUT

Jas*_*n S 10 python binary http put

我不能为我的生活弄清楚如何使用标准Python库在Python 2.7中使用逐字二进制数据执行HTTP PUT请求.

我以为我可以用urllib2来做,但是因为期望它的格式数据而失败urllib2.Requestapplication/x-www-form-urlencoded.我不想对二进制数据进行编码,我只想在包含的标题之后逐字传输

Content-Type: application/octet-stream
Content-Length: (whatever my binary data length is)
Run Code Online (Sandbox Code Playgroud)

这看起来很简单,但我仍然围成一圈,似乎无法弄清楚如何.

我怎样才能做到这一点?(除了打开原始二进制套接字并写入它)

Jas*_*n S 12

我发现了我的问题.似乎在urllib2.Request/中存在一些模糊的行为urllib2.urlopen()(至少在Python 2.7中)

urllib2.Request(url, data, headers)构造似乎期待同类型在其URL和数据参数字符串.

我从文件read()调用中提供了数据参数原始数据(在Python 2.7中以'普通'字符串的形式返回它),但我的url是偶然的Unicode,因为我从另一个函数的结果中连接了一部分URL返回Unicode字符串.

url它试图将data参数"upcast" 为Unicode,而不是试图从Unicode - >普通字符串"向下转换" ,它给了我一个编解码器错误.(奇怪的是,这发生在urllib2.urlopen()函数调用上,而不是urllib2.Request构造函数)

当我改变我的函数调用

# headers contains `{'Content-Type': 'application/octet-stream'}`
r = urllib2.Request(url.encode('utf-8'), data, headers)
Run Code Online (Sandbox Code Playgroud)

它工作得很好.

  • 我有这个确切的问题,真棒,欢呼男人! (2认同)

phi*_*hag 9

您误读了文档:urllib2.Request期望已编码的数据,以及通常表示application/x-www-form-urlencoded格式的POST .您可以自由地关联任何其他二进制数据,如下所示:

import urllib2

data = b'binary-data'
r = urllib2.Request('http://example.net/put', data,
                    {'Content-Type': 'application/octet-stream'})
r.get_method = lambda: 'PUT'
urllib2.urlopen(r)
Run Code Online (Sandbox Code Playgroud)

这将产生您想要的请求:

PUT /put HTTP/1.1
Accept-Encoding: identity
Content-Length: 11
Host: example.net
Content-Type: application/octet-stream
Connection: close
User-Agent: Python-urllib/2.7

binary-data
Run Code Online (Sandbox Code Playgroud)