Question

je voudrais POST multipart / form-data données codées. J'ai trouvé un module externe qu'il fait: http://atlee.ca/software/poster/index .html mais je préfère éviter cette dépendance. Est-il possible de le faire en utilisant les bibliothèques standard?

Merci

Était-ce utile?

La solution

La bibliothèque standard ne supporte pas que . Il est recette de livre de cuisine qui comprend une pièce assez courte le code que vous venez pouvez copier, mais, ainsi que de longues discussions d'alternatives.

Autres conseils

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

L'idée est la même que mais le support de Python 2.x et Python 3. X. Il dispose également d'un générateur de corps pour éviter l'utilisation inutilement 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)

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top