在 Python 3 中为 HTTP 请求创建带有二进制组件的多部分 MIME 消息

Posted

技术标签:

【中文标题】在 Python 3 中为 HTTP 请求创建带有二进制组件的多部分 MIME 消息【英文标题】:Creating a multi-part MIME message with a binary component for an HTTP request in Python 3 【发布时间】:2013-10-01 08:42:48 【问题描述】:

我正在尝试使用 Python 3.3 中的 MIMEApplication 对二进制文件进行编码,作为多部分 MIME HTTP POST 的一部分。我有一个问题,字符 0x0d 被重新解释为换行符 0xa,尽管所有内容都设置为二进制字节。

这是一个最小的测试场景,其中包含一个带有 0x0d 的二进制字符串,但会被误解:

from email.encoders import encode_noop
from email.generator import BytesGenerator
from email.mime.application import MIMEApplication
import io

app = MIMEApplication(b'Q\x0dQ', _encoder=encode_noop)
b = io.BytesIO()
g = BytesGenerator(b)
g.flatten(app)
for i in b.getvalue()[-3:]:
    print("%02x " % i, end="")
print()

当它应该是51 0d 51时,输出是:51 0a 51

请注意,这是为多部分 http POST 消息生成二进制部分。

【问题讨论】:

【参考方案1】:

尝试以下(不指定编码器,使用默认 base64 编码器):

import email
from email.encoders import encode_noop
from email.generator import BytesGenerator
from email.mime.application import MIMEApplication
import io

app = MIMEApplication(b'Q\x0dQ')
b = io.BytesIO()
g = BytesGenerator(b)
g.flatten(app)
msg = email.message_from_bytes(b.getvalue())
assert msg.get_payload(decode=True) == b'Q\x0dQ'

【讨论】:

谢谢!你是对的,这回答了所问的问题。但是您知道我如何将其用作 MIME 多部分消息的一部分吗?这就是我实际需要使用它的方式。【参考方案2】:

我能够通过在 MIMEApplication 内容中放置一个虚拟“标记”来解决我的问题,然后在生成 MIME 消息后替换为真正的二进制文本:

from email.encoders import encode_noop
from email.generator import BytesGenerator
from email.mime.application import MIMEApplication
import io

# Actual binary "file" I want to encode (in real life, this is a file read from disk)
bytesToEncode = b'Q\x0dQ'

# unique marker that we can find and replace after message generation
binarymarker = b'GuadsfjfDaadtjhqadsfqerasdfiojBDSFGgg'

app = MIMEApplication(binarymarker, _encoder=encode_noop)
b = io.BytesIO()
g = BytesGenerator(b)
g.flatten(app, linesep='\r\n')  # linesep for HTTP-compliant header line endings

# replace the marker with the actual binary data, then you have the output you want!
body = b.getvalue().replace(binarymarker, bytesToEncode)

在此之后,body 具有我想要的值,而不会弄乱二进制字节:

b'Content-Type: application/octet-stream\r\nMIME-Version: 1.0\r\n\r\nQ\rQ'

对于多部分消息,您只需先组装多部分消息,然后在最后执行替换()。

【讨论】:

以上是关于在 Python 3 中为 HTTP 请求创建带有二进制组件的多部分 MIME 消息的主要内容,如果未能解决你的问题,请参考以下文章

Ajax 请求复杂类型在 ApiController 参数中为空

在终端中为python 3创建虚拟环境

如何在 python 中为电子邮件创建消息 ID?

通过 iis 上的 python 脚本处理带有 json 的 http post 请求

如何在 Rails 2.3.8 中为 https 请求(即安全连接)查找客户端 IP

带有 Python 请求模块的代理