Search code examples
pythonpostflaskwerkzeug

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

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

@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? 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 ?

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

Python - What type is flask.request.files.stream supposed to be?


Solution

  • You send the files as the parameter named file, so you can't look them up with the name file[]. If you want to get all the files named file as a list, you should use this:

    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:

    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'].)