Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to upload multiple files using flask in python

Tags:

python

flask

Here is my code for multiple files upload:

HTML CODE:

Browse <input type="file" name="pro_attachment1" id="pro_attachment1" multiple>

PYTHON CODE:

pro_attachment = request.files.getlist('pro_attachment1')

for upload in pro_attachment:
    filename = upload.filename.rsplit("/")[0]
    destination = os.path.join(application.config['UPLOAD_FOLDER'], filename)
    print "Accept incoming file:", filename
    print "Save it to:", destination
    upload.save(destination)

But it uploads a single file instead of multiple files.

like image 463
Jenil Ramavat Avatar asked Feb 26 '16 10:02

Jenil Ramavat


2 Answers

How to

In the template, you need to add mulitple attribute in upload input:

<form method="POST" enctype="multipart/form-data">
    <input type="file" name="photos" multiple>
    <input type="submit" value="Submit">
</form>    

Then in view function, the uploaded files can get as a list through request.files.getlist('photos'). Loop this list and call save() method on each item (werkzeug.datastructures.FileStorage) will save them at given path:

import os

from flask import Flask, request, render_template, redirect

app = Flask(__name__)
app.config['UPLOAD_PATH'] = '/the/path/to/save'

@app.route('/upload', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST' and 'photo' in request.files:
        for f in request.files.getlist('photo'):
            f.save(os.path.join(app.config['UPLOAD_PATH'], f.filename))
        return 'Upload completed.'
    return render_template('upload.html')

Furthermore, you may need to use secure_filename() to clean filename:

# ...
from werkzeug.utils import secure_filename
# ...
    for f in request.files.getlist('photo'):
        filename = secure_filename(f.filename)
        f.save(os.path.join(app.config['UPLOAD_PATH'], filename))
        # ...

You can also generate a random filename with this method.

Full demo

View:

import os

from flask import Flask, request, render_template
from werkzeug.utils import secure_filename

app = Flask(__name__)  
app.config['UPLOAD_PATH'] = '/the/path/to/save'

@main.route('/upload', methods=['GET', 'POST'])
def upload():
    form = UploadForm()
    if form.validate_on_submit() and 'photo' in request.files:
        for f in request.files.getlist('photo'):
            filename = secure_filename(f.filename)
            f.save(os.path.join(app.config['UPLOAD_PATH'], filename))
        return 'Upload completed.'
    return render_template('upload.html', form=form)

Form:

from flask_wtf import FlaskForm
from wtforms import SubmitField
from flask_wtf.file import FileField, FileAllowed, FileRequired

class UploadForm(FlaskForm):
    photo = FileField('Image', validators=[
        FileRequired(),
        FileAllowed(photos, 'Image only!')
    ])
    submit = SubmitField('Submit')

Template:

<form method="POST" enctype="multipart/form-data">
    {{ form.hidden_tag() }}
    {{ form.photo(multiple="multiple") }}
    {{ form.submit }}
</form>

More

For better upload experience, you can try Flask-Dropzone.

like image 87
Grey Li Avatar answered Oct 06 '22 15:10

Grey Li


Your code looks perfect. I think the only mistake your making is splitting and taking the first value. And also i dont know about the rsplit(), but the split() works perfect for me.

HTML CODE


<input id="upload_img" name="zip_folder"  type="file" multiple  webkitdirectory  >

PYTHON CODE

@app.route('/zipped',methods = ['GET', 'POST'])
def zipped():
    if request.method == 'POST':
        f = request.files.getlist("zip_folder")
        print f
        for zipfile in f:
            filename = zipfile.filename.split('/')[1]
            print zipfile.filename.split('/')[1]
            zipfile.save(os.path.join(app.config['ZIPPED_FILE'], filename))
        return render_template('final.html')
like image 3
Jeremy Avatar answered Oct 06 '22 16:10

Jeremy