【问题标题】:Python standard library to POST multipart/form-data encoded data用于发布多部分/表单数据编码数据的 Python 标准库
【发布时间】:2010-11-19 05:20:50
【问题描述】:

我想发布多部分/表单数据编码数据。 我找到了一个外部模块:http://atlee.ca/software/poster/index.html 但是我宁愿避免这种依赖。有没有办法使用标准库来做到这一点?

谢谢

【问题讨论】:

    标签: python encoding post urllib multipart


    【解决方案1】:

    标准库does not currently support that。不过,cookbook recipe 包含一段相当短的代码,您可能只想复制它,以及对替代方案的长时间讨论。

    【讨论】:

      【解决方案2】:

      这是一个旧线程,但仍然很受欢迎,所以这是我仅使用标准模块的贡献。

      思路与here相同,但支持Python 2.x和Python 3.x。 它还有一个主体生成器来避免不必要的内存使用。

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

      演示

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

      【讨论】:

      • 终于找到了一个仅适用于标准库的 Python 3 的解决方案。
      【解决方案3】:

      你不能用标准库快速做到这一点。但是,请参阅此 PyMOTW 中的 MultiPartForm 类。您可能可以使用或修改它来完成您需要的任何事情:

      猜你喜欢
      • 2012-04-17
      • 2016-11-08
      • 1970-01-01
      • 1970-01-01
      • 2015-10-31
      • 2019-11-19
      • 2017-06-06
      • 2016-11-11
      • 1970-01-01
      相关资源
      最近更新 更多