用于 POST 多部分/表单数据编码数据的 Python 标准库
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1270518/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python standard library to POST multipart/form-data encoded data
提问by hoju
I would like to POST multipart/form-data encoded data. I have found an external module that does it: http://atlee.ca/software/poster/index.htmlhowever I would rather avoid this dependency. Is there a way to do this using the standard libraries?
我想发布多部分/表单数据编码的数据。我找到了一个外部模块:http: //atlee.ca/software/poster/index.html但是我宁愿避免这种依赖。有没有办法使用标准库来做到这一点?
thanks
谢谢
采纳答案by Martin v. L?wis
The standard library does not currently support that. There is cookbook recipethat includes a fairly short piece of code that you just may want to copy, though, along with long discussions of alternatives.
回答by ticapix
It's an old thread but still a popular one, so here is my contribution using only standard modules.
这是一个旧线程,但仍然很受欢迎,所以这是我仅使用标准模块的贡献。
The idea is the same than herebut support Python 2.x and Python 3.x. It also has a body generator to avoid unnecessarily memory usage.
想法与此处相同,但支持 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()
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)
回答by ars
You can't do this with the stdlib quickly. Howevewr, see the MultiPartForm
class in this PyMOTW. You can probably use or modify that to accomplish whatever you need:
你不能用 stdlib 快速做到这一点。但是,请参阅MultiPartForm
此 PyMOTW 中的课程。您可能可以使用或修改它来完成您需要的任何操作: