时间:2015-10-27 13:28:52

标签: python web-services client python-requests

我正在使用请求库编写Web Service Client。我在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)
  

B' \ r \ N - c00750d1-8ce4-4d29-8390-b50bf02a92cc \ r \ nContent处置:   形式数据;名称=" playbackHash" \ r \ nContent型:   应用/八位字节流\ r \ n \ r \ n \ X16 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ x00serialization ::归档\ n \ X00 \ X04 \ X08 \ X04   ....   X00 \ x00R \ X94 \ x9bp \ x8c \ X00 \ r \ n - c00750d1-8ce4-4d29-8390-b50bf02a92cc \ r \ nContent处置:   形式数据;名称=" usersMFCC" \ r \ nContent型:   应用/八位字节流\ r \ n \ r \ n \ X16 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ x00serialization ::归档\ 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 \ nContent处置:   形式数据; name =" scoreAndStatus" \ r \ nConContent-Type:application / json;   字符集= UTF-8 \ r \ n \ r \ N {" lexLikelihood":1.544479046897232" overalScore值": - 南," playbackLikelihood": - INF,& #34;状态" {"的errorCode":0,"的errorMessage":""}} \ r \ N - c00750d1-8ce4-4d29 -8390-b50bf02a92cc - \ r \ n'

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

3 个答案:

答案 0 :(得分:12)

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

$ pip install requests-toolbelt

安装后

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)

答案 1 :(得分:3)

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

答案 2 :(得分:2)

下面是working example的解析多部分数据。您可以在交互式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()

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

    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

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

请谨慎考虑保存文件的安全性。您可能无法信任发布的文件名,例如,在某些Web服务器上,它可能以../../filename.sh开头,因此,如果您尝试写入/my-folder/../../filename.sh,则攻击者可能会将恶意文件放置在文件名之外。您尝试存储文件的位置。还建议在信任文件本身之前对文件作为允许的类型进行强力验证。您不想让攻击者覆盖系统上的任何文件。