简体   繁体   English

使用 Flask 上传文件列表时 request.files 为空

[英]request.files is empty when uploading a list of files with Flask

I need to upload multiple files to a flask endpoint in a list.我需要将多个文件上传到列表中的 flask 端点。 But request.files is empty when I try to upload a list of files, even if the list contains only one element.但是当我尝试上传文件列表时request.files是空的,即使列表只包含一个元素。 Look at this minimal example:看看这个最小的例子:

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

The last assertions 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

Do you have any idea how I can fix this?你知道我该如何解决这个问题吗?

The problem with second request is that you are trying to send an array of files along with some data which is not possible.第二个请求的问题是您试图发送一组文件以及一些不可能的数据。 If you see the request structure for request.post() method it looks something like this:如果您看到 request.post() 方法的请求结构,它看起来像这样:

{
    "args": {},
    "data": "",
    "files": {},
    "form": {
       
    },
    "headers": {
    },
    "json": null,
    "origin": "",
    "url": ""
}

So you will have to send all the files outside the array (in files param) while your text should go in "form" param.因此,您必须将所有文件发送到数组之外(在 files 参数中),而您的文本应该 go 在“form”参数中。 For sending multiple files you can do something like this:要发送多个文件,您可以执行以下操作:

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

Source: https://requests.readthedocs.io/en/master/user/advanced/#post-multiple-multipart-encoded-files来源: https://requests.readthedocs.io/en/master/user/advanced/#post-multiple-multipart-encoded-files

Edit 1: For test client, you will have to create your data object like below:编辑 1:对于测试客户端,您必须创建数据 object,如下所示:

data_1 = {
    'a': '42',
    'blue:': open('blue.jpg', mode='rb'),
    'red:': open('red.jpg', mode='rb'),
    'text': 'this is blue',
}

I solved the problem: Using MultiDict solves the problem:我解决了这个问题:使用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

Output: Output:

[]
[<FileStorage: 'blue.jpg' ('image/jpeg')>, <FileStorage: 'blue.jpg' ('image/jpeg')>]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM