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

时间:2012-01-02 22:26:42

标签: python http binary put

我不能为我的生活弄清楚如何使用标准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)

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

我该怎么做? (除了打开一个原始二进制套接字并写入它)

4 个答案:

答案 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()