我不能为我的生活弄清楚如何使用标准Python库在Python 2.7中使用逐字二进制数据执行HTTP PUT请求。
我认为我可以使用urllib2,但that fails,因为urllib2.Request
期望其数据为application/x-www-form-urlencoded
格式。我不想对二进制数据进行编码,我只想在包含
Content-Type: application/octet-stream
Content-Length: (whatever my binary data length is)
这看起来很简单,但我仍然围成一圈,似乎无法弄清楚如何。
我该怎么做? (除了打开一个原始二进制套接字并写入它)
答案 0 :(得分:12)
我发现了我的问题。在urllib2.Request
/ urllib2.urlopen()
中似乎存在一些模糊的行为(至少在Python 2.7中)
urllib2.Request(url, data, headers)
构造函数似乎期望在其url和data参数中使用相同类型的字符串。
我从文件read()
调用中提供数据参数原始数据(在Python 2.7中以'普通'字符串的形式返回它),但我的网址是偶然的Unicode,因为我连接了一部分返回Unicode字符串的另一个函数的结果中的URL。
而不是尝试从Unicode“向下”url
- >普通的字符串,它试图将data
参数“upcast”为Unicode,它给了我一个编解码器错误。 (奇怪的是,这发生在urllib2.urlopen()
函数调用上,而不是urllib2.Request
构造函数)
当我将函数调用更改为
时# headers contains `{'Content-Type': 'application/octet-stream'}`
r = urllib2.Request(url.encode('utf-8'), data, headers)
它运作良好。
答案 1 :(得分:9)
您误读了文档:urllib2.Request
期望数据已编码,而POST通常表示application/x-www-form-urlencoded
格式。您可以自由地关联任何其他二进制数据,如下所示:
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)
这将产生您想要的请求:
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
答案 2 :(得分:4)
您是否考虑/尝试过使用httplib?
HTTPConnection.request(方法,网址[,正文[,标题]])
这将使用HTTP请求方法向服务器发送请求 方法和选择器URL。如果身体参数存在,那么 应该是标题完成后要发送的数据字符串。 或者,它可以是一个打开的文件对象,在这种情况下 发送文件的内容;这个文件对象应该支持fileno() 和read()方法。标题Content-Length自动设置为 正确的价值。 headers参数应该是extra的映射 随请求一起发送的HTTP标头。
答案 3 :(得分:1)
这段剪辑让我为PUT画像:
在HTTPS网站上。如果您不需要HTTPS,请使用 改为httplib.HTTPConnection(URL)。
import httplib
import ssl
API_URL="api-mysight.com"
TOKEN="myDummyToken"
IMAGE_FILE="myimage.jpg"
imageID="myImageID"
URL_PATH_2_USE="/My/image/" + imageID +"?objectId=AAA"
headers = {"Content-Type":"application/octet-stream", "X-Access-Token": TOKEN}
imgData = open(IMAGE_FILE, "rb")
REQUEST="PUT"
conn = httplib.HTTPSConnection(API_URL, context=ssl.SSLContext(ssl.PROTOCOL_TLSv1))
conn.request(REQUEST, URL_PATH_2_USE, imgData, headers)
response = conn.getresponse()
result = response.read()