解析从发布请求中收到的multipart/form-data

use*_*037 9 python client web-services python-requests

我正在使用请求库编写Web服务客户端.我在multipart/form-data中获取包含文件和text-json的数据.我不知道如何解析它.是否有一个适当的库来解析python中的multipart/form-data格式,还是应该自己编写解析器?

我的代码:

data = {
  "prototypeModel" :('prototypeModel', open(prototypeModel, 'rb'), 'application/octet-stream', {'Expires': '0'}),
  "mfcc_1" : ('mfcc', open(mfcc_1, 'rb'), 'application/octet-stream', {'Expires': '0'}),
  "mfcc_2" : ('mfcc', open(mfcc_2, 'rb'), 'application/octet-stream', {'Expires': '0'}),
  "mfcc_3" : ('mfcc', open(mfcc_3, 'rb'), 'application/octet-stream', {'Expires': '0'}),
}

print( '---------------------- start enroll ----------------------')
testEnrollResponse = requests.post(server+sessionID, files = data, json = declaredParameters)
Run Code Online (Sandbox Code Playgroud)

b'\ r \n - c00750d1-8ce4-4d29-8390-b50bf02a92cc\r \nConContent-Disposition:form-data; name ="playbackHash"\ r \nContent-Type:application/octet-stream\r \n\r \n\x16\x00\x00\x00\x00\x00\x00\x00serialization :: archive \n\x00\x04\x08\x04 .... x00\x00R\x94\x9bp\x8c\x00\r \n - c00750d1-8ce4-4d29-8390-b50bf02a92cc\r \nConContent-Disposition:form-data; name ="usersMFCC"\ r \nContent-Type:application/octet-stream\r \n\r \n\x16\x00\x00\x00\x00\x00\x00\x00serialization :: archive \n\x00\x04\X08\X04\X08\X01\X00\X00\X00\X00\X00\X00\X00\X00\XF8\X16\X00\X00\X00\X00\X00\x00u\XBD\XB4 /\xda1\XEA\XBF\X0F \固定的\ XA2 <\ xc9\XF8\XE7\XBF?\ XD5\xf06u\XE7\XF0\XBF\XD 4\x8d\XD 4\xa1F\XBE\X03 @\x85X!\ X19\xd8A\X06 @\x8co\xf7\r .....
x80\xd9\x95Yxn\xd0?\ r \n - c00750d1-8ce4-4d29-8390-b50bf02a92cc\r \nConContent-Disposition:form-data; name ="scoreAndStatus"\ r \nConContent-Type:application/json; 字符集= UTF-8\r \n\r\N { "lexLikelihood":1.544479046897232 "overalScore值": -南"playbackLikelihood": - INF, "状态":{ "的errorCode":0 "的errorMessage":" "}}\r\N - c00750d1-8ce4-4d29-8390-b50bf02a92cc -\r\N"

我用"....."替换了更多的二进制数据

Ian*_*sco 14

如果您收到multipart/form-data回复,可以使用requests-toolbelt库解析它,如下所示:

$ pip install requests-toolbelt
Run Code Online (Sandbox Code Playgroud)

安装后

from requests_toolbelt.multipart import decoder

testEnrollResponse = requests.post(...)
multipart_data = decoder.MultipartDecoder.from_response(testEnrollResponse)

for part in multipart_data.parts:
    print(part.content)  # Alternatively, part.text if you want unicode
    print(part.headers)
Run Code Online (Sandbox Code Playgroud)


小智 8

下面是解析多部分数据的工作示例。您可以在交互式 python 提示符下尝试一下。

import email

msg = email.message_from_string('''\
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="    XXXX"

--    XXXX
Content-Type: text/plain


--    XXXX
Content-Type: text/plain

--    XXXX--
''')

msg.is_multipart()
Run Code Online (Sandbox Code Playgroud)

一旦您知道它在您的系统上运行,您就可以根据 POST 数据构建您自己的电子邮件消息并以相同的方式解析它。如果您将原始帖子正文作为字符串,则可以在请求标头中找到其余的必要信息。为了清楚起见,我在此处添加了缩进,块字符串中不应有多余的缩进。

    epost_data = '''\
MIME-Version: 1.0
Content-Type: %s

%s''' % (self.headers['content-type'], post_data)

    msg = email.message_from_string(post_data)

    if msg.is_multipart():
        for part in msg.get_payload():
            name = part.get_param('name', header='content-disposition')
            filename = part.get_param('filename', header='content-disposition')
            # print 'name %s' % name # "always" there
            # print 'filename %s' % filename # only there for files...
            payload = part.get_payload(decode=True)
            print payload[:100] # output first 100 characters
Run Code Online (Sandbox Code Playgroud)

第一个%s将替换为内容类型,第二个将替换为post_data. 然后您可以将有效负载写入文件等。

请小心考虑保存文件的安全影响。您可能无法信任发布的文件名,它可能从../../filename.sh某些 Web 服务器上开始,因此,如果您尝试写入,/my-folder/../../filename.sh攻击者可能会将恶意文件放置在您尝试存储文件的位置之外。还建议在信任文件本身之前对文件是否为允许的类型进行严格验证。您不希望让攻击者覆盖您系统上的任何文件。


Ale*_*gin 6

Flask 的代码示例,使用https://github.com/defnull/multipart

import multipart as mp
from multipart import tob

try:
    from io import BytesIO
except ImportError:
    from StringIO import StringIO as BytesIO

@app.route('/', methods=["GET","POST"])
def index():
        ...
        elif flask.request.method == "POST":
                data = flask.request.data
                s = data.split("\r")[0][2:]
                p = mp.MultipartParser(BytesIO(tob(data)),s)
                blob = p.parts()[0].value
                f = open("file.bin","wb")
                f.write(blob.encode("latin-1"))
                f.close()
Run Code Online (Sandbox Code Playgroud)

  • 这有有用的信息,事实上,当我试图为服务器端寻找类似的东西时,这篇文章就出现了。即使问题是双向的,它说收到请求,可能来自客户端。 (2认同)