简体   繁体   English

如何使用Flask测试客户端发布多个文件?

[英]How to POST multiple FILES using Flask test client?

In order to test a Flask application, I got a flask test client POSTing request with files as attachment 为了测试Flask应用程序,我得到了一个烧瓶测试客户端POST请求,文件作为附件

def make_tst_client_service_call1(service_path, method, **kwargs):
    _content_type = kwargs.get('content-type','multipart/form-data')
    with app.test_client() as client:
        return client.open(service_path, method=method,
                           content_type=_content_type, buffered=True,               
                                             follow_redirects=True,**kwargs)

def _publish_a_model(model_name, pom_env):
    service_url = u'/publish/'
    scc.data['modelname'] = model_name
    scc.data['username'] = "BDD Script"
    scc.data['instance'] = "BDD Stub Simulation"
    scc.data['timestamp'] = datetime.now().strftime('%d-%m-%YT%H:%M')
    scc.data['file'] = (open(file_path, 'rb'),file_name)
    scc.response = make_tst_client_service_call1(service_url, method, data=scc.data)

Flask Server end point code which handles the above POST request is something like this 处理上述POST请求的Flask Server端点代码是这样的

@app.route("/publish/", methods=['GET', 'POST'])
def publish():
    if request.method == 'POST':
        LOG.debug("Publish POST Service is called...")
        upload_files = request.files.getlist("file[]")
        print "Files :\n",request.files
        print "Upload Files:\n",upload_files
        return render_response_template()

I get this Output 我得到了这个输出

Files:
ImmutableMultiDict([('file', <FileStorage: u'Single_XML.xml' ('application/xml')>)])

Upload Files:
[]

If I change 如果我改变

scc.data['file'] = (open(file_path, 'rb'),file_name)

into (thinking that it would handle multiple files) 进(认为它会处理多个文件)

scc.data['file'] = [(open(file_path, 'rb'),file_name),(open(file_path, 'rb'),file_name1)]

I still get similar Output: 我仍然得到类似的输出:

Files:
ImmutableMultiDict([('file', <FileStorage: u'Single_XML.xml' ('application/xml')>), ('file', <FileStorage: u'Second_XML.xml' ('application/xml')>)])

Upload Files:
[]

Question: Why request.files.getlist("file[]") is returning an empty list? 问题:为什么request.files.getlist(“file []”)返回一个空列表? How can I post multiple files using flask test client, so that it can be retrieved using request.files.getlist("file[]") at flask server side ? 如何使用flask测试客户端发布多个文件,以便可以在flask服务器端使用request.files.getlist(“file []”)检索它?

Note: 注意:

  • I would like to have flask client I dont want curl or any other client based solutions. 我想有烧瓶客户端我不想要卷曲或任何其他基于客户端的解决方案。
  • I dont want to post single file in multiple requests 我不想在多个请求中发布单个文件

Thanks 谢谢

Referred these links already: 已经提到这些链接:

Flask and Werkzeug: Testing a post request with custom headers Flask和Werkzeug:使用自定义标头测试发布请求

Python - What type is flask.request.files.stream supposed to be? Python - flask.request.files.stream应该是什么类型的?

You send the files as the parameter named file , so you can't look them up with the name file[] . 您将文件作为名为file的参数发送,因此您无法使用名称file[]查找它们。 If you want to get all the files named file as a list, you should use this: 如果要将名为file所有file作为列表获取,则应使用以下命令:

upload_files = request.files.getlist("file")

On the other hand, if you really want to read them from file[] , then you need to send them like that: 另一方面,如果你真的想从file[]读取它们,那么你需要像这样发送它们:

scc.data['file[]'] = # ...

(The file[] syntax is from PHP and it's used only on the client side. When you send the parameters named like that to the server, you still access them using $_FILES['file'] .) file[]语法来自PHP,它仅在客户端使用。当您将名称相同的参数发送到服务器时,您仍然可以使用$_FILES['file']访问它们。)

Lukas already addressed this,just providing these info as it may help someone Lukas已经解决了这个问题,只提供这些信息,因为它可能对某人有帮助

Werkzeug client is doing some clever stuff by storing requests data in MultiDict Werkzeug客户端通过在MultiDict中存储请求数据来做一些聪明的事情

@native_itermethods(['keys', 'values', 'items', 'lists', 'listvalues'])
class MultiDict(TypeConversionDict):
    """A :class:`MultiDict` is a dictionary subclass customized to deal with
    multiple values for the same key which is for example used by the parsing
    functions in the wrappers.  This is necessary because some HTML form
    elements pass multiple values for the same key.

    :class:`MultiDict` implements all standard dictionary methods.
    Internally, it saves all values for a key as a list, but the standard dict
    access methods will only return the first value for a key. If you want to
    gain access to the other values, too, you have to use the `list` methods as
    explained below.

getList call looks for a given key in the "requests" dictionary. getList调用在“请求”字典中查找给定键。 If the key doesn't exist, it returns empty list. 如果密钥不存在,则返回空列表。

def getlist(self, key, type=None):
    """Return the list of items for a given key. If that key is not in the
    `MultiDict`, the return value will be an empty list.  Just as `get`
    `getlist` accepts a `type` parameter.  All items will be converted
    with the callable defined there.

    :param key: The key to be looked up.
    :param type: A callable that is used to cast the value in the
                 :class:`MultiDict`.  If a :exc:`ValueError` is raised
                 by this callable the value will be removed from the list.
    :return: a :class:`list` of all the values for the key.
    """
    try:
        rv = dict.__getitem__(self, key)
    except KeyError:
        return []
    if type is None:
        return list(rv)
    result = []
    for item in rv:
        try:
            result.append(type(item))
        except ValueError:
            pass
    return result

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

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