невозможно добавить двоичный файл изображения в multipart / form-data - PullRequest
0 голосов
/ 23 июня 2018

Я получил ошибку: ожидаемый экземпляр str, найдены байты, когда я пытался добавить двоичный файл изображения в multipart / form-data.

Проблема в том, что я пытался добавить imageData в двоичном формате к строкам.Есть ли способ добавить двоичное изображение к данным multipart / form?

Я в своем уме, был бы признателен за помощь.

imageData = request.FILES['filePath'].read()


content_type, request_body = encode_multipart_formdata([('include_target_data', targetMetaDataRet),
                                                     ('max_num_results', str(maxNoResultRet))],
                                                     [('image', imagePath, imageData)])

def encode_multipart_formdata(fields, files):

    BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
    CRLF = '\r\n'
    lines = []
    for (key, value) in fields:
        lines.append('--' + BOUNDARY)
        lines.append('Content-Disposition: form-data; name="%s"' % key)
        lines.append('')
        lines.append(value)
    for (key, filename, value) in files:
        lines.append('--' + BOUNDARY)
        lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
        lines.append('Content-Type: %s' % get_content_type(filename))
        lines.append('')
        lines.append(value)
    lines.append('--' + BOUNDARY + '--')
    lines.append('')
    body = CRLF.join(lines)
    content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
    return content_type, body

Трассировка:

  35.            response = get_response(request)

  128.           response = self.process_exception_by_middleware(e, request)

  126.           response = wrapped_callback(request, *callback_args, **callback_kwargs)

  166.           [('image', imagePath, imageData)])

  232.           body = CRLF.join(lines)

Exception Type: TypeError at /identify_shrine
Exception Value: sequence item 12: expected str instance, bytes found

согласно запросу @coltoneakins Я изменил тело запроса в байтах, но, похоже, получаю неверный запросошибка любая идея почему?

Код:

content_type = 'multipart/form-data; boundary=----------ThIs_Is_tHe_bouNdaRY_$'
request_body = '----------ThIs_Is_tHe_bouNdaRY_$' +  '\n'+'Content-Disposition: form-data; name="include_target_data"' + '\n' + '\n' + 'top'+ '\n' + '----------ThIs_Is_tHe_bouNdaRY_$' +'\n' + 'Content-Disposition: form-data; name="max_num_results"' + '\n' + '\n' + '1' + '\n' + '----------ThIs_Is_tHe_bouNdaRY_$' +'\n' + 'Content-Disposition: form-data; name="image"; filename="img_2.jpg"' + '\n' + 'Content-Type: image/jpeg' + '\n' + '\n'
request_body1 = request_body.encode('utf-8')
request_body2 = imageData
request_body3 = ('\n' + '\n' + '----------ThIs_Is_tHe_bouNdaRY_$').encode('utf-8')
request_body4 = request_body1 + request_body2 + request_body3

content_type_bare = 'multipart/form-data'

# Sign the request and get the Authorization header
# use client key
auth_header = authorization_header_for_request(CLIENT_ACCESS_KEY, CLIENT_SECRET_KEY, HTTP_METHOD, request_body4,
                                               content_type_bare,
                                               date, path)

request_headers = {
    'Accept': 'application/json',
    'Authorization': auth_header,
    'Content-Type': content_type,
    'Date': date
}
try:
    # Make the request over HTTPS on port 443
    connection = http.client.HTTPSConnection(CLOUD_RECO_API_ENDPOINT, 443)
    connection.request(HTTP_METHOD, path, request_body4, request_headers)

    response = connection.getresponse()
    response_body = response.read()
    reason = response.reason
    status = response.status

finally:
    connection.close()

1 Ответ

0 голосов
/ 23 июня 2018

У вас есть проблема с типом в вашем коде. Вы получаете ожидаемый экземпляр типа TypeError, найдены байты , потому что вы пытаетесь join () список, который содержит типы str и байтов типов в Python.

Посмотрите на эти строки в вашем коде:

    for (key, filename, value) in files:
    lines.append('--' + BOUNDARY)
    lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
    lines.append('Content-Type: %s' % get_content_type(filename))
    lines.append('')
    lines.append(value) # <---------- THIS IS BYTES, EVERYTHING ELSE IS STR
lines.append('--' + BOUNDARY + '--')
lines.append('')
body = CRLF.join(lines) # <---------- AHHH RED FLAG!!!

CRLF - это тип str . Но значение (которое добавляется в список строк ) составляет байт . Это означает, что вы получите строк , содержащих оба типа str и bytes . Когда вы отправляете изображение через запрос mulitpart / form-data, все тело запроса - байты. Таким образом, вам нужно использовать join () только с байтами типами.

Вот что вы делаете:

body = CRLF.join(lines)

что на самом деле:

'\r\n, i am a str'.join(['i am also str', b'I am not a str, I am bytes']) # <-- NO

Это то, что вам нужно делать:

b'I am bytes'.join([b'I am also bytes', b'Me too!'])

Также, чтобы вы знали, библиотека запросов предоставляет механизмы для отправки файлов. См. Параметр files в документации по запросам или ответ StackOverflow:

https://stackoverflow.com/a/12385661/9347694

Так что, возможно, вам не нужно изобретать колесо здесь. Запросы будут многокомпонентно кодировать файл и составлять запрос для вас.

...