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

发布于 2024-12-24 01:08:00 字数 611 浏览 3 评论 0原文

我一生都无法弄清楚如何使用标准 Python 库在 Python 2.7 中使用逐字二进制数据执行 HTTP PUT 请求。

我以为我可以用 urllib2 做到这一点,但是 失败 因为 urllib2.Request 期望其数据在application/x-www-form-urlencoded 格式。我不想对二进制数据进行编码,我只想在包含

Content-Type: application/octet-stream
Content-Length: (whatever my binary data length is)

This 的标头之后逐字传输它,这看起来很简单,但我一直在兜圈子,似乎不知道如何进行。

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

I cannot for the life of me figure out how to perform an HTTP PUT request with verbatim binary data in Python 2.7 with the standard Python libraries.

I thought I could do it with urllib2, but that fails because urllib2.Request expects its data in application/x-www-form-urlencoded format. I do not want to encode the binary data, I just want to transmit it verbatim, after the headers that include

Content-Type: application/octet-stream
Content-Length: (whatever my binary data length is)

This seems so simple, but I keep going round in circles and can't seem to figure out how.

How can I do this? (aside from open up a raw binary socket and write to it)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

苦笑流年记忆 2024-12-31 01:08:00

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

urllib2.Request(url, data, headers) 构造函数似乎期望其 url 和 data 参数中包含相同类型的字符串。

我从文件 read() 调用中提供数据参数原始数据(在 Python 2.7 中以“纯”字符串的形式返回它),但我的 url 意外地是 Unicode,因为我连接了一个来自另一个返回 Unicode 字符串的函数结果的 URL 部分。

而不是尝试从 Unicode“向下转换”url ->纯字符串,它尝试将 data 参数“向上转换”为 Unicode,并给出了编解码器错误。 (奇怪的是,这种情况发生在 urllib2.urlopen() 函数调用上,而不是 urllib2.Request 构造函数上)

当我更改函数调用时,

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

它工作正常。

I found out my problem. It seems there is some obscure behavior in urllib2.Request / urllib2.urlopen() (at least in Python 2.7)

The urllib2.Request(url, data, headers) constructor seems to expect the same type of string in its url and data parameters.

I was giving the data parameter raw data from a file read() call (which in Python 2.7 returns it in the form of a 'plain' string), but my url was accidentally Unicode because I concatenated a portion of the URL from the result of another function which returned Unicode strings.

Rather than trying to "downcast" url from Unicode -> plain strings, it tried to "upcast" the data parameter to Unicode, and it gave me a codec error. (oddly enough, this happens on the urllib2.urlopen() function call, not the urllib2.Request constructor)

When I changed my function call to

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

it worked fine.

去了角落 2024-12-31 01:08:00

您误读了文档: 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

You're misreading the documentation: urllib2.Request expects the data already encoded, and for POST that usually means the application/x-www-form-urlencoded format. You are free to associate any other, binary data, like this:

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)

This will produce the request you want:

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
萌辣 2024-12-31 01:08:00

您是否考虑/尝试过使用 httplib

HTTPConnection.request(方法, url[, body[, headers]])

这将使用 HTTP 请求方法向服务器发送请求
方法和选择器 url。如果 body 参数存在,则
应该是标头完成后要发送的一串数据。
或者,它可能是一个打开的文件对象,在这种情况下
文件内容已发送;这个文件对象应该支持 fileno()
和 read() 方法。标头 Content-Length 自动设置为
正确的值。 headers 参数应该是 extra 的映射
与请求一起发送的 HTTP 标头。

Have you considered/tried using httplib?

HTTPConnection.request(method, url[, body[, headers]])

This will send a request to the server using the HTTP request method
method and the selector url. If the body argument is present, it
should be a string of data to send after the headers are finished.
Alternatively, it may be an open file object, in which case the
contents of the file is sent; this file object should support fileno()
and read() methods. The header Content-Length is automatically set to
the correct value. The headers argument should be a mapping of extra
HTTP headers to send with the request.

温折酒 2024-12-31 01:08:00

这个片段帮助我将图像放置

在 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()

This snipped worked for me to PUT an image:

on HTTPS site. If you don't need HTTPS, use
httplib.HTTPConnection(URL) instead.

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文