解析一串多部分数据
Parse a string of multipart data
我有一个字符串(这里是 base64 解码),看起来像这样:
----------------------------212550847697339237761929
Content-Disposition: form-data; name="preferred_name"; filename="file1.rtf"
Content-Type: application/rtf
{\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf830
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
\margl1440\margr1440\vieww10800\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
\f0\fs24 \cf0 testing123FILE1}
----------------------------212550847697339237761929
Content-Disposition: form-data; name="to_process"; filename="file2.rtf"
Content-Type: application/rtf
{\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf830
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
\margl1440\margr1440\vieww10800\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
\f0\fs24 \cf0 testing123FILE212341234}
----------------------------212550847697339237761929--
我在一个简单的网页上生成此文件,该网页通过使用 API 网关的 PUT 请求将几个文件上传到 AWS Lambda 脚本。应该注意的是,我从 API 网关得到的是一个 Base64 字符串,然后我将其解码为上面的字符串。
上面的字符串是我的 Lambda 脚本从 API 网关接收到的数据。 我想做的是解析这个字符串,以便检索 Python 2.7 中包含的数据。 我已经尝试过 cgi
class 并使用 cgi.parse_multipart()
方法,但是,我找不到将字符串转换为所需参数的方法。有什么建议吗?
Comment: is it robust and spec compliant?
只要你的数据符合这个先决条件:
- 第一个线是边界
- 以下 Header 以 空 行终止
- 每个消息部分以边界
终止
Comment: What if the content is binary like a JPEG stream?
这很可能会中断,因为使用了 String 方法并且阅读内容使用 .readline()
这取决于 New Line.
因此,从 BASE64 到 decode
然后 unpack
Multipart 是 错误的 方法!
Comment: If there's a version reusing a common library
如果您能够提供您的数据作为标准 MIME 您可以使用以下消息:
import email
msg = email.message_from_string(mimeHeader+data)
print('is_multipart:{}'.format(msg.is_multipart()))
for part in msg.walk():
if part.get_content_maintype() == 'multipart':
continue
filename = part.get_filename()
payload = part.get_payload(decode=True)
print('{} filename:{}\n{}'.format(part.get_content_type(), filename, payload))
Output:
is_multipart:True
application/rtf filename:file1.rtf
b'{\rtf1\x07nsi\x07nsicpg1252\cocoartf1504\cocoasubrtf830\n{\x0conttbl\x0c0\x0cswiss\x0ccharset0'... (omitted for brevity)
application/rtf filename:file2.rtf
b'{\rtf1\x07nsi\x07nsicpg1252\cocoartf1504\cocoasubrtf830\n{\x0conttbl\x0c0\x0cswiss\x0ccharset0'... (omitted for brevity)
Question: Parse a string of multipart data
纯Python解,例如:
import re, io
with io.StringIO(data) as fh:
parts = []
part_line = []
part_fname = None
new_part = None
robj = re.compile('.+filename=\"(.+)\"')
while True:
line = fh.readline()
if not line: break
if not new_part:
new_part = line[:-1]
if line.startswith(new_part):
if part_line:
parts.append({'filename':part_fname, 'content':''.join(part_line)})
part_line = []
while line and line != '\n':
_match = robj.match(line)
if _match: part_fname = _match.groups()[0]
line = fh.readline()
else:
part_line.append(line)
for part in parts:
print(part)
Output:
{'filename': 'file1.rtf', 'content': '{\rtf1\x07nsi\x07nsicpg1252\cocoartf1504\cocoasubrtf830\n... (omitted for brevity)
{'filename': 'file2.rtf', 'content': '{\rtf1\x07nsi\x07nsicpg1252\cocoartf1504\cocoasubrtf830\n... (omitted for brevity)
使用 Python 测试:3.4.2
如果您正在使用 API,最好使用 json 格式的数据。
您可以使用请求模块向 API 发送 PUT 请求,它会 return 您可以使用 [=12= 方法从中轻松检索 json 数据的响应对象]response.json()
我有一个字符串(这里是 base64 解码),看起来像这样:
----------------------------212550847697339237761929
Content-Disposition: form-data; name="preferred_name"; filename="file1.rtf"
Content-Type: application/rtf
{\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf830
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
\margl1440\margr1440\vieww10800\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
\f0\fs24 \cf0 testing123FILE1}
----------------------------212550847697339237761929
Content-Disposition: form-data; name="to_process"; filename="file2.rtf"
Content-Type: application/rtf
{\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf830
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
\margl1440\margr1440\vieww10800\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
\f0\fs24 \cf0 testing123FILE212341234}
----------------------------212550847697339237761929--
我在一个简单的网页上生成此文件,该网页通过使用 API 网关的 PUT 请求将几个文件上传到 AWS Lambda 脚本。应该注意的是,我从 API 网关得到的是一个 Base64 字符串,然后我将其解码为上面的字符串。
上面的字符串是我的 Lambda 脚本从 API 网关接收到的数据。 我想做的是解析这个字符串,以便检索 Python 2.7 中包含的数据。 我已经尝试过 cgi
class 并使用 cgi.parse_multipart()
方法,但是,我找不到将字符串转换为所需参数的方法。有什么建议吗?
Comment: is it robust and spec compliant?
只要你的数据符合这个先决条件:
- 第一个线是边界
- 以下 Header 以 空 行终止
- 每个消息部分以边界 终止
Comment: What if the content is binary like a JPEG stream?
这很可能会中断,因为使用了 String 方法并且阅读内容使用 .readline()
这取决于 New Line.
因此,从 BASE64 到 decode
然后 unpack
Multipart 是 错误的 方法!
Comment: If there's a version reusing a common library
如果您能够提供您的数据作为标准 MIME 您可以使用以下消息:
import email
msg = email.message_from_string(mimeHeader+data)
print('is_multipart:{}'.format(msg.is_multipart()))
for part in msg.walk():
if part.get_content_maintype() == 'multipart':
continue
filename = part.get_filename()
payload = part.get_payload(decode=True)
print('{} filename:{}\n{}'.format(part.get_content_type(), filename, payload))
Output:
is_multipart:True application/rtf filename:file1.rtf b'{\rtf1\x07nsi\x07nsicpg1252\cocoartf1504\cocoasubrtf830\n{\x0conttbl\x0c0\x0cswiss\x0ccharset0'... (omitted for brevity) application/rtf filename:file2.rtf b'{\rtf1\x07nsi\x07nsicpg1252\cocoartf1504\cocoasubrtf830\n{\x0conttbl\x0c0\x0cswiss\x0ccharset0'... (omitted for brevity)
Question: Parse a string of multipart data
纯Python解,例如:
import re, io
with io.StringIO(data) as fh:
parts = []
part_line = []
part_fname = None
new_part = None
robj = re.compile('.+filename=\"(.+)\"')
while True:
line = fh.readline()
if not line: break
if not new_part:
new_part = line[:-1]
if line.startswith(new_part):
if part_line:
parts.append({'filename':part_fname, 'content':''.join(part_line)})
part_line = []
while line and line != '\n':
_match = robj.match(line)
if _match: part_fname = _match.groups()[0]
line = fh.readline()
else:
part_line.append(line)
for part in parts:
print(part)
Output:
{'filename': 'file1.rtf', 'content': '{\rtf1\x07nsi\x07nsicpg1252\cocoartf1504\cocoasubrtf830\n... (omitted for brevity) {'filename': 'file2.rtf', 'content': '{\rtf1\x07nsi\x07nsicpg1252\cocoartf1504\cocoasubrtf830\n... (omitted for brevity)
使用 Python 测试:3.4.2
如果您正在使用 API,最好使用 json 格式的数据。 您可以使用请求模块向 API 发送 PUT 请求,它会 return 您可以使用 [=12= 方法从中轻松检索 json 数据的响应对象]response.json()