Как опубликовать несколько файлов с помощью Flask test client?

для того, чтобы протестировать приложение колбы, я получил запрос на размещение тестового клиента колбы с файлами в качестве вложения

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, который обрабатывает вышеуказанный запрос POST, что-то вроде этого

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

Я получаю этот выход

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

Upload Files:
[]

если я изменю

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

в (думая, что он будет обрабатывать несколько файлов)

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

Я все еще получаю аналогичный выход:

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

Upload Files:
[]

вопрос: Почему? запрос.файлы.getlist ("file []") возвращает пустой список? Как я могу опубликовать несколько файлов с помощью тестового клиента flask, чтобы его можно было получить с помощью запрос.файлы.getlist ("file []") на стороне сервера колбы ?

Примечание:

  • я хотел бы иметь клиента колбы, я не хочу curl или любые другие решения на основе клиента.
  • я не хочу публиковать один файл в нескольких запросах

спасибо

называют эти ссылки уже:

колба и Werkzeug: тестирование запроса post с пользовательскими заголовками

Python - какой тип колбы.запрос.файлы.поток должен быть?

2 ответов


отправить файлы в качестве параметра с именем file, поэтому вы не можете найти их с именем file[]. Если вы хотите получить все файлы с именем file в качестве списка вы должны использовать следующее:

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

С другой стороны, если вы действительно хотите, чтобы прочитать их из file[], тогда вам нужно отправить их вот так:

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

(The file[] синтаксис из PHP, и он используется только на стороне клиента. Когда вы отправляете параметры с таким именем на сервер, вы все равно получаете доступ их использование $_FILES['file'].)


Лукас уже обратился к этому,просто предоставив эту информацию, поскольку это может помочь кому-то

клиент 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 ищет данный ключ в словаре" запросы". Если ключ не существует, он возвращает пустой список.

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