dberube4

Multiparts

Nov 1st, 2012
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.16 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. ####
  4. # 02/2006 Will Holcomb <[email protected]>
  5. #
  6. # This library is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU Lesser General Public
  8. # License as published by the Free Software Foundation; either
  9. # version 2.1 of the License, or (at your option) any later version.
  10. #
  11. # This library is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14. # Lesser General Public License for more details.
  15. #
  16. """
  17. Usage:
  18.  Enables the use of multipart/form-data for posting forms
  19.  
  20. Inspirations:
  21.  Upload files in python:
  22.    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
  23.  urllib2_file:
  24.    Fabien Seisen: <[email protected]>
  25.  
  26. Example:
  27.  import MultipartPostHandler, urllib2, cookielib
  28.  
  29.  cookies = cookielib.CookieJar()
  30.  opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies),
  31.                                MultipartPostHandler.MultipartPostHandler)
  32.  params = { "username" : "bob", "password" : "riviera",
  33.             "file" : open("filename", "rb") }
  34.  opener.open("http://wwww.bobsite.com/upload/", params)
  35.  
  36. Further Example:
  37.  The main function of this file is a sample which downloads a page and
  38.  then uploads it to the W3C validator.
  39. """
  40.  
  41. import urllib
  42. import urllib2
  43. import mimetools, mimetypes
  44. import os, stat
  45.  
  46. class Callable:
  47.     def __init__(self, anycallable):
  48.         self.__call__ = anycallable
  49.  
  50. # Controls how sequences are uncoded. If true, elements may be given multiple values by
  51. #  assigning a sequence.
  52. doseq = 1
  53.  
  54. class MultipartPostHandler(urllib2.BaseHandler):
  55.     handler_order = urllib2.HTTPHandler.handler_order - 10 # needs to run first
  56.  
  57.     def http_request(self, request):
  58.         data = request.get_data()
  59.         if data is not None and type(data) != str:
  60.             v_files = []
  61.             v_vars = []
  62.             try:
  63.                  for(key, value) in data.items():
  64.                      if type(value) == file:
  65.                          v_files.append((key, value))
  66.                      else:
  67.                          v_vars.append((key, value))
  68.             except TypeError:
  69.                 systype, value, traceback = sys.exc_info()
  70.                 raise TypeError, "not a valid non-string sequence or mapping object", traceback
  71.  
  72.             if len(v_files) == 0:
  73.                 data = urllib.urlencode(v_vars, doseq)
  74.             else:
  75.                 boundary, data = self.multipart_encode(v_vars, v_files)
  76.                 contenttype = 'multipart/form-data; boundary=%s' % boundary
  77.                 if(request.has_header('Content-Type')
  78.                    and request.get_header('Content-Type').find('multipart/form-data') != 0):
  79.                     print "Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data')
  80.                 request.add_unredirected_header('Content-Type', contenttype)
  81.  
  82.             request.add_data(data)
  83.         return request
  84.  
  85.     def multipart_encode(vars, files, boundary = None, buffer = None):
  86.         if boundary is None:
  87.             boundary = mimetools.choose_boundary()
  88.         if buffer is None:
  89.             buffer = ''
  90.         for(key, value) in vars:
  91.             buffer += '--%s\r\n' % boundary
  92.             buffer += 'Content-Disposition: form-data; name="%s"' % key
  93.             buffer += '\r\n\r\n' + value + '\r\n'
  94.         for(key, fd) in files:
  95.             file_size = os.fstat(fd.fileno())[stat.ST_SIZE]
  96.             filename = fd.name.split('/')[-1]
  97.             contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
  98.             buffer += '--%s\r\n' % boundary
  99.             buffer += 'Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename)
  100.             buffer += 'Content-Type: %s\r\n' % contenttype
  101.             # buffer += 'Content-Length: %s\r\n' % file_size
  102.             fd.seek(0)
  103.             buffer += '\r\n' + fd.read() + '\r\n'
  104.         buffer += '--%s--\r\n\r\n' % boundary
  105.         return boundary, buffer
  106.     multipart_encode = Callable(multipart_encode)
  107.  
  108.     https_request = http_request
Advertisement
Add Comment
Please, Sign In to add comment