使用Python 3创建包含二进制组件的多部分MIME消息的HTTP请求

2024-06-16 11:30:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用python3.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 0a 51,而它应该是51 0d 51

注意,这是为多部分httppost消息生成一个二进制部分。在


Tags: 文件fromioimportapp编码email二进制
2条回答

我可以通过在MIMEApplication内容中放入一个虚拟的“marker”,然后在生成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有了我想要的值,而不会弄乱二进制字节:

^{pr2}$

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

尝试以下操作(不指定编码器,使用默认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'

相关问题 更多 >