request.files 使用 Flask 上传文件列表时为空
request.files is empty when uploading a list of files with Flask
我需要将多个文件上传到列表中的烧瓶端点。但是当我尝试上传文件列表时 request.files
是空的,即使该列表只包含一个元素。看看这个最小的例子:
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['POST'])
def hello_world():
assert len(request.files) > 0
return 'Hello, World'
data_1 = {
'a': '42',
'file:': open('blue.jpg', mode='rb'),
'text': 'this is blue',
}
data_2 = {
'a': '42',
'gallery': [{
'file:': open('blue.jpg', mode='rb'),
'text': 'this is blue',
}],
}
client = app.test_client()
res = client.post('/', data=data_1, content_type='multipart/form-data')
assert res.status_code == 200 # all fine here
res = client.post('/', data=data_2, content_type='multipart/form-data')
assert res.status_code == 200 # fails
最后一个断言失败:
[2021-03-03 15:29:46,597] ERROR in app: Exception on / [POST]
Traceback (most recent call last):
File "/home/wsontopski/PycharmProjects/pythonProject1/venv/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/home/wsontopski/PycharmProjects/pythonProject1/venv/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/wsontopski/PycharmProjects/pythonProject1/venv/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/wsontopski/PycharmProjects/pythonProject1/venv/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/wsontopski/PycharmProjects/pythonProject1/venv/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/home/wsontopski/PycharmProjects/pythonProject1/venv/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/wsontopski/PycharmProjects/pythonProject1/main.py", line 7, in hello_world
assert len(request.files) > 0
AssertionError
Traceback (most recent call last):
File "/home/wsontopski/PycharmProjects/pythonProject1/main.py", line 27, in <module>
assert res.status_code == 200
AssertionError
你知道我该如何解决这个问题吗?
第二个请求的问题是您试图发送一组文件以及一些不可能的数据。如果您看到 request.post() 方法的请求结构,它看起来像这样:
{
"args": {},
"data": "",
"files": {},
"form": {
},
"headers": {
},
"json": null,
"origin": "",
"url": ""
}
因此您必须将所有文件发送到数组之外(在文件参数中),而您的文本应该在“表单”参数中。要发送多个文件,您可以这样做:
>>> url = 'https://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)
来源:https://requests.readthedocs.io/en/master/user/advanced/#post-multiple-multipart-encoded-files
编辑 1:
对于测试客户端,您必须创建如下数据对象:
data_1 = {
'a': '42',
'blue:': open('blue.jpg', mode='rb'),
'red:': open('red.jpg', mode='rb'),
'text': 'this is blue',
}
我解决了问题:使用MultiDict
解决了问题:
data_1 = {
'a': '42',
'file': open('blue.jpg', mode='rb'),
'file2': open('blue.jpg', mode='rb'),
'text': 'this is blue',
}
data_2 = MultiDict([
('a', '42'),
('file', open('blue.jpg', mode='rb')),
('file', open('blue.jpg', mode='rb')),
('text', 'this is blue'),
])
client = app.test_client()
res = client.post('/', data=data_1, content_type='multipart/form-data')
assert res.status_code == 200
res = client.post('/', data=data_2, content_type='multipart/form-data')
assert res.status_code == 200
输出:
[]
[<FileStorage: 'blue.jpg' ('image/jpeg')>, <FileStorage: 'blue.jpg' ('image/jpeg')>]
我需要将多个文件上传到列表中的烧瓶端点。但是当我尝试上传文件列表时 request.files
是空的,即使该列表只包含一个元素。看看这个最小的例子:
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['POST'])
def hello_world():
assert len(request.files) > 0
return 'Hello, World'
data_1 = {
'a': '42',
'file:': open('blue.jpg', mode='rb'),
'text': 'this is blue',
}
data_2 = {
'a': '42',
'gallery': [{
'file:': open('blue.jpg', mode='rb'),
'text': 'this is blue',
}],
}
client = app.test_client()
res = client.post('/', data=data_1, content_type='multipart/form-data')
assert res.status_code == 200 # all fine here
res = client.post('/', data=data_2, content_type='multipart/form-data')
assert res.status_code == 200 # fails
最后一个断言失败:
[2021-03-03 15:29:46,597] ERROR in app: Exception on / [POST]
Traceback (most recent call last):
File "/home/wsontopski/PycharmProjects/pythonProject1/venv/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/home/wsontopski/PycharmProjects/pythonProject1/venv/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/wsontopski/PycharmProjects/pythonProject1/venv/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/wsontopski/PycharmProjects/pythonProject1/venv/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/wsontopski/PycharmProjects/pythonProject1/venv/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/home/wsontopski/PycharmProjects/pythonProject1/venv/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/wsontopski/PycharmProjects/pythonProject1/main.py", line 7, in hello_world
assert len(request.files) > 0
AssertionError
Traceback (most recent call last):
File "/home/wsontopski/PycharmProjects/pythonProject1/main.py", line 27, in <module>
assert res.status_code == 200
AssertionError
你知道我该如何解决这个问题吗?
第二个请求的问题是您试图发送一组文件以及一些不可能的数据。如果您看到 request.post() 方法的请求结构,它看起来像这样:
{
"args": {},
"data": "",
"files": {},
"form": {
},
"headers": {
},
"json": null,
"origin": "",
"url": ""
}
因此您必须将所有文件发送到数组之外(在文件参数中),而您的文本应该在“表单”参数中。要发送多个文件,您可以这样做:
>>> url = 'https://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)
来源:https://requests.readthedocs.io/en/master/user/advanced/#post-multiple-multipart-encoded-files
编辑 1: 对于测试客户端,您必须创建如下数据对象:
data_1 = {
'a': '42',
'blue:': open('blue.jpg', mode='rb'),
'red:': open('red.jpg', mode='rb'),
'text': 'this is blue',
}
我解决了问题:使用MultiDict
解决了问题:
data_1 = {
'a': '42',
'file': open('blue.jpg', mode='rb'),
'file2': open('blue.jpg', mode='rb'),
'text': 'this is blue',
}
data_2 = MultiDict([
('a', '42'),
('file', open('blue.jpg', mode='rb')),
('file', open('blue.jpg', mode='rb')),
('text', 'this is blue'),
])
client = app.test_client()
res = client.post('/', data=data_1, content_type='multipart/form-data')
assert res.status_code == 200
res = client.post('/', data=data_2, content_type='multipart/form-data')
assert res.status_code == 200
输出:
[]
[<FileStorage: 'blue.jpg' ('image/jpeg')>, <FileStorage: 'blue.jpg' ('image/jpeg')>]