pythonrequests上传文件
参考
django 上传文件
临时文件,可以获取名字
内存文件
需求
django 收取到前端上传的文件后转发到微信服务器
requsts 上传文件
https://2.python-requests.org//zh_CN/latest/user/advanced.html#streaming-uploads
流式上传
with open("massive-body") as f: requests.post("http://some.url/streamed", data=f)
块编码请求
def gen(): yield "hi"
yield "there"
requests.post("http://some.url/chunked", data=gen())
POST 多个分块编码的文件
>>> url = "http://httpbin.org/post">>> multiple_files = [
("images", ("foo.png", open("foo.png", "rb"), "image/png")),
("images", ("bar.png", open("bar.png", "rb"), "image/png"))]
>>> r = requests.post(url, files=multiple_files)
>>> r.text
{
...
"files": {"images": "data:image/png;base64,iVBORw ...."}
"Content-Type": "multipart/form-data; boundary=3131623adb2043caaeb5538cc7aa0b3a",
...
}
requests.models.py
请求编码混入
class RequestEncodingMixin(object): @staticmethod
def _encode_files(files, data):
"""Build the body for a multipart/form-data request.
Will successfully encode files when passed as a dict or a list of
tuples. Order is retained if data is a list of tuples but arbitrary
if parameters are supplied as a dict.
The tuples may be 2-tuples (filename, fileobj), 3-tuples (filename, fileobj, contentype) # 文件格式
or 4-tuples (filename, fileobj, contentype, custom_headers).
"""
if (not files):
raise ValueError("Files must be provided.")
elif isinstance(data, basestring):
raise ValueError("Data must not be a string.")
new_fields = []
fields = to_key_val_list(data or {})
files = to_key_val_list(files or {})
for field, val in fields:
if isinstance(val, basestring) or not hasattr(val, "__iter__"):
val = [val]
for v in val:
if v is not None:
# Don"t call str() on bytestrings: in Py3 it all goes wrong.
if not isinstance(v, bytes):
v = str(v)
new_fields.append(
(field.decode("utf-8") if isinstance(field, bytes) else field,
v.encode("utf-8") if isinstance(v, str) else v))
# 遍历files获取2/3元组/list格式的数据.
for (k, v) in files:
# support for explicit filename
ft = None
fh = None
if isinstance(v, (tuple, list)):
if len(v) == 2:
fn, fp = v
elif len(v) == 3:
fn, fp, ft = v
else:
fn, fp, ft, fh = v
else:
fn = guess_filename(v) or k
fp = v
if isinstance(fp, (str, bytes, bytearray)): # 内存数据
fdata = fp
elif hasattr(fp, "read"): # 文件对象, 支持read
fdata = fp.read()
elif fp is None:
continue
else:
fdata = fp
rf = RequestField(name=k, data=fdata, filename=fn, headers=fh)
rf.make_multipart(content_type=ft)
new_fields.append(rf)
body, content_type = encode_multipart_formdata(new_fields)
return body, content_type
django 中上传文件
settings.py
# 设置上传文件为临时文件,避免使用内存文件FILE_UPLOAD_HANDLERS = [
"django.core.files.uploadhandler.TemporaryFileUploadHandler",
]
serializers.py 上传文件字段
class MaterialCreateSerializer(serializers.ModelSerializer): name = serializers.CharField(
required=False, max_length=30, help_text=u"标题")
content = serializers.FileField(
required=True, help_text=u"材料内容",
validators=[
FileExtensionValidator(
["png", "jpg", "jpeg", "mp4", "mp3"]
)
]
)
views.py
class XxxView(generics.GenericAPIView):
permission_classes = ()
authentication_classes = ()
serializer_class = MaterialCreateSerializer
def post(self, request, *args, **kwargs):
"""
诗经里景区服务号上传摇一摇功能图片素材
---
parameters:
- name: object
pytype: serializers.MaterialCreateSerializer
paramType: body
"""
serializer = self.get_serializer(data=request.data)
if not serializer.is_valid():
logger.error(
"WXApiView serializer err:{}".format(serializer.errors))
return Response(
serializer.errors, status=status.HTTP_400_BAD_REQUEST)
data = serializer.validated_data
url = data.get("url")
file_data = data.get("image")
if file_data.closed:
fp = open(file_data.file.name, "r") # 从不执行
elif isinstance(file_data, TemporaryUploadedFile):
fp = file_data.file.file # file对象
# 使用requets中的多文件上传, 也可使用但文件
multiple_files = [
("file", ("file", fp, file_data.content_type)),
]
resp = _post(url=url, files=multiple_files)
if not fp.closed:
fp.close()
return resp
note
- requests 方法中调用fp.read后,不会调用fp.close
- django orm 读取数据后,会主动关闭, 默认存储oss 中也会fp.read->fp.close。
以上是 pythonrequests上传文件 的全部内容, 来源链接: utcz.com/z/511507.html