Path: blob/master/timing/test_scripts/MultipartPostHandler.py
447 views
#!/usr/bin/python12####3# 02/2006 Will Holcomb <[email protected]>4#5# This library is free software; you can redistribute it and/or6# modify it under the terms of the GNU Lesser General Public7# License as published by the Free Software Foundation; either8# version 2.1 of the License, or (at your option) any later version.9#10# This library is distributed in the hope that it will be useful,11# but WITHOUT ANY WARRANTY; without even the implied warranty of12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU13# Lesser General Public License for more details.14#15# 7/2/10 refactored by Jason Grout--made two functions instead of a class16# 7/26/07 Slightly modified by Brian Schneider17# in order to support unicode files ( multipart_encode function )18# from http://peerit.blogspot.com/2007/07/multipartposthandler-doesnt-work-for.html1920"""21Usage:22Enables the use of multipart/form-data for posting forms2324Inspirations:25Upload files in python:26http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/14630627urllib2_file:28Fabien Seisen: <[email protected]>2930Example:31import MultipartPostHandler, urllib2, cookielib3233cookies = cookielib.CookieJar()34opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies),35MultipartPostHandler.MultipartPostHandler)36params = { "username" : "bob", "password" : "riviera",37"file" : open("filename", "rb") }38opener.open("http://wwww.bobsite.com/upload/", params)3940Further Example:41The main function of this file is a sample which downloads a page and42then uploads it to the W3C validator.43"""4445import urllib46import urllib247import mimetools, mimetypes48import os, stat49from cStringIO import StringIO5051# Controls how sequences are uncoded. If true, elements may be given multiple values by52# assigning a sequence.53doseq = 1545556def encode_request(request):57data = request.get_data()58if data is not None and type(data) != str:59v_files = []60v_vars = []61if isinstance(data, dict):62data=data.items()63try:64for(key, value) in data:65if type(value) == file:66v_files.append((key, value))67else:68v_vars.append((key, value))69except TypeError:70systype, value, traceback = sys.exc_info()71raise TypeError, "not a valid non-string sequence or mapping object", traceback7273if len(v_files) == 0:74data = urllib.urlencode(v_vars, doseq)75else:76boundary, data = multipart_encode(v_vars, v_files)7778contenttype = 'multipart/form-data; boundary=%s' % boundary79if(request.has_header('Content-Type')80and request.get_header('Content-Type').find('multipart/form-data') != 0):81print "Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data')82request.add_unredirected_header('Content-Type', contenttype)8384request.add_data(data)8586return request8788def multipart_encode(vars, files, boundary = None, buf = None):89if boundary is None:90boundary = mimetools.choose_boundary()91if buf is None:92buf = StringIO()93for(key, value) in vars:94buf.write('--%s\r\n' % boundary)95buf.write('Content-Disposition: form-data; name="%s"' % key)96buf.write('\r\n\r\n%s\r\n'%value)97for(key, fd) in files:98file_size = os.fstat(fd.fileno())[stat.ST_SIZE]99filename = fd.name.split('/')[-1]100contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'101buf.write('--%s\r\n' % boundary)102buf.write('Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename))103buf.write('Content-Type: %s\r\n' % contenttype)104# buffer += 'Content-Length: %s\r\n' % file_size105fd.seek(0)106buf.write('\r\n' + fd.read() + '\r\n')107buf.write('--' + boundary + '--\r\n\r\n')108buf = buf.getvalue()109return boundary, buf110111112113