Используя MultipartPostHandler к данным формы POST с Python

Проблема: При РЕГИСТРАЦИИ данных с Python urllib2 всеми данными является URL, закодированный и отправленный как Тип контента: application/x-www-form-urlencoded. При загрузке файлов Тип контента должен вместо этого быть установлен на multipart/form-data и содержание, которое будет закодировано MIME.

Для обхождения этого ограничения, некоторые резкие кодеры создали библиотеку под названием MultipartPostHandler, который создает OpenerDirector, для которого можно использовать с urllib2 главным образом автоматически POST с multipart/form-data. Копия этой библиотеки здесь: MultipartPostHandler не работает на файлы Unicode

Я плохо знаком с Python и не могу заставить эту библиотеку работать. Я выписал по существу следующий код. Когда я получаю его в локальном Прокси HTTP, я вижу, что данными является все еще закодированный URL и не многослойные закодированный MIME. Помогите мне выяснить то, что я делаю неправильно или лучший способ сделать это. Спасибо :-)

FROM_ADDR = 'my@email.com'

try:
    data = open(file, 'rb').read()
except:
    print "Error: could not open file %s for reading" % file
    print "Check permissions on the file or folder it resides in"
    sys.exit(1)

# Build the POST request
url = "http://somedomain.com/?action=analyze"       
post_data = {}
post_data['analysisType'] = 'file'
post_data['executable'] = data
post_data['notification'] = 'email'
post_data['email'] = FROM_ADDR

# MIME encode the POST payload
opener = urllib2.build_opener(MultipartPostHandler.MultipartPostHandler)
urllib2.install_opener(opener)
request = urllib2.Request(url, post_data)
request.set_proxy('127.0.0.1:8080', 'http') # For testing with Burp Proxy

# Make the request and capture the response
try:
    response = urllib2.urlopen(request)
    print response.geturl()
except urllib2.URLError, e:
    print "File upload failed..."

EDIT1: Спасибо за Ваш ответ. Я знаю о решении ActiveState httplib этого (я связался с ним выше). Я абстрагировал бы далеко проблему и использовал бы минимальный объем кода, чтобы продолжить использовать urllib2, как я был. Какая-либо идея, почему новичок не устанавливается и используется?

47
задан abdullahkhawer 17 September 2019 в 17:52
поделиться

0 ответов

Кажется, что самый легкий и самый совместимый способ обойти эту проблему состоит в том, чтобы использовать модуль 'плаката'.

# test_client.py
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
import urllib2

# Register the streaming http handlers with urllib2
register_openers()

# Start the multipart/form-data encoding of the file "DSC0001.jpg"
# "image1" is the name of the parameter, which is normally set
# via the "name" parameter of the HTML <input> tag.

# headers contains the necessary Content-Type and Content-Length
# datagen is a generator object that yields the encoded parameters
datagen, headers = multipart_encode({"image1": open("DSC0001.jpg")})

# Create the Request object
request = urllib2.Request("http://localhost:5000/upload_image", datagen, headers)
# Actually do the request, and get the response
print urllib2.urlopen(request).read()

Это работало прекрасное, и я не должен был унавоживать с httplib. Модуль доступен здесь: http://atlee.ca/software/poster/index.html

57
ответ дан Dan 26 November 2019 в 19:21
поделиться

Найденный этим рецептом для регистрации многослойного использования httplib непосредственно (никакие внешние библиотеки не включили),

import httplib
import mimetypes

def post_multipart(host, selector, fields, files):
    content_type, body = encode_multipart_formdata(fields, files)
    h = httplib.HTTP(host)
    h.putrequest('POST', selector)
    h.putheader('content-type', content_type)
    h.putheader('content-length', str(len(body)))
    h.endheaders()
    h.send(body)
    errcode, errmsg, headers = h.getreply()
    return h.file.read()

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

def get_content_type(filename):
    return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
38
ответ дан Community 26 November 2019 в 19:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: