Issue #10 new

Handle file inputs with multiple files

jfinkels
created an issue

In a file input field which allows multiple elements, like <input type="file" multiple="multiple" name="files">, I seem to be validating only the first file. The form should handle multiple files from the request.files object.

Comments (3)

  1. Dan Jacob repo owner

    This is most likely a Werkzeug/Flask issue, as Flask-WTF simply assigns whatever value is in request.files[name] to the "file" attribute. If that happens to be a list, then it will assign a list.

    What value do you get if you do "print request.files" inside your view ?

  2. jfinkels reporter

    Given the following Flask application:

    from flask import Flask, request, render_template
    from flaskext.wtf import Form, FileField
    
    app = Flask(__name__)
    app.config['DEBUG'] = True
    app.config['SECRET_KEY'] = '\xef<\xd63\xc0\x9b\x04\xbe1\x91G\xd2RQ\x1e\xedM\x9a\
     \xae\xf1C\xe3z'
    
    class UploadForm(Form):
        files = FileField('Choose some files')
    
    @app.route('/', methods=['GET', 'POST'])
    def upload():
        form = UploadForm(request.form)
        print 'request.files:', request.files
        print 'request.files["files"]:', request.files['files']
        return render_template('upload.html', form=form)
    
    if __name__ == '__main__':
        app.run()
    

    and the corresponding template:

    <!doctype html>
    <html>
    <head><title>Test</title></head>
    <body>
    <form action="{{ url_for('upload') }}" method="post" enctype="multipart/form-da\
    ta">
      <p>{{ form.files.label }}: {{ form.files(multiple="multiple") }}</p>
      <input type="submit" value="Submit" />
    </form>
    </body>
    </html>
    

    The output after selecting three files is as follows:

    request.files: ImmutableMultiDict([('files', <FileStorage: u'1.txt' ('text/plain')>), ('files', <FileStorage: u'2.txt' ('text/plain')>), ('files', <FileStorage: u'3.txt' ('text/plain')>)])
    request.files["files"] <FileStorage: u'1.txt' ('text/plain')>
    

    So the problem is that the multiple elements are not stored as a dictionary mapping names to lists, but rather as a werkzeug ImmutableMultiDict mapping one name to multiple individual files.

  3. Asdine El Hrychy

    I know this post is old but here is some extra code

    @app.route('/', methods=['GET', 'POST']) 
    def upload():
        form = UploadForm(request.form)
        files = request.files.getlist('files')
        for file in files:
            print file.filename
        return render_template('upload.html', form=form)
    

    getlist permits to get an array of all the files, you can then access any information you need inside each row

  4. Log in to comment