使用 MultipartPostHandler 通过 Python 发布表单数据

问题描述

问题:当使用 Python 的 urllib2 发布数据时,所有数据都经过 URL 编码并作为 Content-Type: application/x-www-form-urlencoded 发送.上传文件时,Content-Type 应该设置为 multipart/form-data 并且内容是 MIME 编码的.

Problem: When POSTing data with Python's urllib2, all data is URL encoded and sent as Content-Type: application/x-www-form-urlencoded. When uploading files, the Content-Type should instead be set to multipart/form-data and the contents be MIME-encoded.

为了解决这个限制,一些敏锐的编码人员创建了一个名为 MultipartPostHandler 的库,它创建了一个 OpenerDirector,您可以将其与 urllib2 一起使用,以自动使用 multipart/form-data 进行 POST.这个库的副本在这里:MultipartPostHandler 不适用于Unicode 文件

To get around this limitation some sharp coders created a library called MultipartPostHandler which creates an OpenerDirector you can use with urllib2 to mostly automatically POST with multipart/form-data. A copy of this library is here: MultipartPostHandler doesn't work for Unicode files

我是 Python 新手,无法让这个库正常工作.我基本上写了以下代码.当我在本地 HTTP 代理中捕获它时,我可以看到数据仍然是 URL 编码的,而不是多部分 MIME 编码的.请帮助我找出我做错了什么或更好的方法来完成这项工作.谢谢:-)

I am new to Python and am unable to get this library to work. I wrote out essentially the following code. When I capture it in a local HTTP proxy, I can see that the data is still URL encoded and not multi-part MIME-encoded. Please help me figure out what I am doing wrong or a better way to get this done. Thanks :-)

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..."

感谢您的回复.我知道 ActiveState httplib 解决方案(我在上面链接到它).我宁愿抽象出问题并使用最少的代码来继续使用 urllib2.知道为什么没有安装和使用开启器吗?

Thanks for your response. I'm aware of the ActiveState httplib solution to this (I linked to it above). I'd rather abstract away the problem and use a minimal amount of code to continue using urllib2 how I have been. Any idea why the opener isn't being installed and used?


解决方案

似乎解决这个问题的最简单和最兼容的方法是使用海报"模块.

It seems that the easiest and most compatible way to get around this problem is to use the 'poster' module.

# 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

This worked perfect and I didn't have to muck with httplib. The module is available here: http://atlee.ca/software/poster/index.html

相关文章