Парсить строку составные данные
у меня есть строка (base64 декодирована здесь), которая выглядит так:
----------------------------212550847697339237761929
Content-Disposition: form-data; name="preferred_name"; filename="file1.rtf"
Content-Type: application/rtf
{rtf1ansiansicpg1252cocoartf1504cocoasubrtf830
{fonttblf0fswissfcharset0 Helvetica;}
{colortbl;red255green255blue255;}
{*expandedcolortbl;;}
margl1440margr1440vieww10800viewh8400viewkind0
pardtx720tx1440tx2160tx2880tx3600tx4320tx5040tx5760tx6480tx7200tx7920tx8640pardirnaturalpartightenfactor0
f0fs24 cf0 testing123FILE1}
----------------------------212550847697339237761929
Content-Disposition: form-data; name="to_process"; filename="file2.rtf"
Content-Type: application/rtf
{rtf1ansiansicpg1252cocoartf1504cocoasubrtf830
{fonttblf0fswissfcharset0 Helvetica;}
{colortbl;red255green255blue255;}
{*expandedcolortbl;;}
margl1440margr1440vieww10800viewh8400viewkind0
pardtx720tx1440tx2160tx2880tx3600tx4320tx5040tx5760tx6480tx7200tx7920tx8640pardirnaturalpartightenfactor0
f0fs24 cf0 testing123FILE212341234}
----------------------------212550847697339237761929--
Я создаю это на простой веб-странице, которая загружает пару файлов в скрипт AWS Lambda через запрос PUT с помощью шлюза API. Следует отметить, что то, что я получаю от шлюза API, является строкой Base64, которую я затем декодирую в строку выше.
строка выше-это данные, которые мой лямбда-скрипт получает от шлюза API. что я хотел бы сделать, это разобрать эту строку чтобы получить данные, содержащиеся в Python 2.7. я экспериментировал с cgi
классе и использовать cgi.parse_multipart()
метод, однако, я не могу найти способ преобразовать строку в требуемые аргументы. Есть советы?
2 ответов
комментарий: он робастн и спецификации уступчивые?
пока ваши данные следуют этим предварительным условиям:
- на первый строка граница
- следующий заголовок завершается с пустой строка
- каждая часть сообщения завершается с граница
комментарий: что если содержимое бинарном потоке jpeg?
это, вероятно, сломать, как есть строка используемые методы и чтение содержимого используют .readline()
которых зависит Новая Строка.
Поэтому к decode
из BASE64, а затем unpack
Multipart являются неправильно подход!
комментарий: если есть версия, повторно использующая общую библиотеку
если вы можете предоставить свои данные в качестве стандарта МИМ сообщение вы можете использовать следующее:
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))
выход:
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)
вопрос: разбор строки составных данных
чистое решение 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)
выход:
{'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. Вы можете использовать модуль запросов для отправки запроса PUT в API, и он вернет вам объект ответа, из которого вы можете легко получить данные json с помощью метода ответ.в JSON()