2009-08-13 7 views

Répondre

5

Vous ne pouvez pas le faire rapidement avec stdlib. Howevewr, voir la classe MultiPartForm dans ce PyMOTW. Vous pouvez probablement utiliser ou modifier que pour accomplir tout ce dont vous avez besoin:

8

Il est un vieux fil, mais encore populaire, alors voici ma contribution en utilisant des modules standards seulement.

L'idée est la même que here mais supporte Python 2.x et Python 3.x. Il a également un générateur de corps pour éviter inutilement l'utilisation de la mémoire.

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() 

Démo

# 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

Enfin une solution qui fonctionne pour Python 3 avec la bibliothèque standard. –

Questions connexes