2009-08-13 10 views

Antwort

5

Sie können dies nicht schnell mit der STDLIB tun. Wie auch immer, siehe die MultiPartForm Klasse in diesem PyMOTW. Sie können sich wahrscheinlich, dass verwenden oder modifizieren zu erreichen, was Sie brauchen:

8

Es ist ein alter Thread, aber immer noch ein beliebter ein, also hier ist mein Beitrag nur mit Standardmodulen.

Die Idee ist die gleiche als here, aber unterstützen Python 2.x und Python 3.x. Es hat auch einen Body-Generator, um unnötigen Speicherverbrauch zu vermeiden.

import codecs 
import mimetypes 
import sys 
import uuid 
try: 
    import io 
except ImportError: 
    pass # io is requiered in python3 but not available in python2 

class MultipartFormdataEncoder(object): 
    def __init__(self): 
     self.boundary = uuid.uuid4().hex 
     self.content_type = 'multipart/form-data; boundary={}'.format(self.boundary) 

    @classmethod 
    def u(cls, s): 
     if sys.hexversion < 0x03000000 and isinstance(s, str): 
      s = s.decode('utf-8') 
     if sys.hexversion >= 0x03000000 and isinstance(s, bytes): 
      s = s.decode('utf-8') 
     return s 

    def iter(self, fields, files): 
     """ 
     fields is a sequence of (name, value) elements for regular form fields. 
     files is a sequence of (name, filename, file-type) elements for data to be uploaded as files 
     Yield body's chunk as bytes 
     """ 
     encoder = codecs.getencoder('utf-8') 
     for (key, value) in fields: 
      key = self.u(key) 
      yield encoder('--{}\r\n'.format(self.boundary)) 
      yield encoder(self.u('Content-Disposition: form-data; name="{}"\r\n').format(key)) 
      yield encoder('\r\n') 
      if isinstance(value, int) or isinstance(value, float): 
       value = str(value) 
      yield encoder(self.u(value)) 
      yield encoder('\r\n') 
     for (key, filename, fd) in files: 
      key = self.u(key) 
      filename = self.u(filename) 
      yield encoder('--{}\r\n'.format(self.boundary)) 
      yield encoder(self.u('Content-Disposition: form-data; name="{}"; filename="{}"\r\n').format(key, filename)) 
      yield encoder('Content-Type: {}\r\n'.format(mimetypes.guess_type(filename)[0] or 'application/octet-stream')) 
      yield encoder('\r\n') 
      with fd: 
       buff = fd.read() 
       yield (buff, len(buff)) 
      yield encoder('\r\n') 
     yield encoder('--{}--\r\n'.format(self.boundary)) 

    def encode(self, fields, files): 
     body = io.BytesIO() 
     for chunk, chunk_len in self.iter(fields, files): 
      body.write(chunk) 
     return self.content_type, body.getvalue() 

Demo

# some utf8 key/value pairs 
fields = [('প্রায়', 42), ('bar', b'23'), ('foo', 'ން:')] 
files = [('myfile', 'image.jpg', open('image.jpg', 'rb'))] 

# iterate and write chunk in a socket 
content_type, body = MultipartFormdataEncoder().encode(fields, files) 
+0

schließlich eine Lösung, die nur für Python 3 mit der Standardbibliothek arbeitet. –