helloflask / flask-dropzone

Upload files in Flask application with Dropzone.js.
https://flask-dropzone.readthedocs.io
MIT License
249 stars 70 forks source link

Multiple File Upload and Server Side Validation #33

Open skewwhiff opened 4 years ago

skewwhiff commented 4 years ago

Hi @greyli , Awesome plugin. I am using it to upload multiple files along with some server-side validation. Is there a way to return the individual status of each uploaded file? It is clear how to do it when only one file is being uploaded from https://github.com/greyli/flask-dropzone/blob/master/docs/advanced.rst#server-side-validation

Here's a barebones implementation of what works so far. I currently just append all error messages with the corresponding filename:

:
: 
app.config['DROPZONE_UPLOAD_MULTIPLE'] = True
app.config['DROPZONE_MAX_FILE_SIZE'] = 10
app.config['DROPZONE_MAX_FILES'] = 5
app.config['DROPZONE_UPLOAD_ON_CLICK'] = True
: 
: 
@app.route('<upload_url>', methods=['GET', 'POST'])
def file_upload():
  if request.method=='POST':
    errors = []
    for key, f in request.files.items():
        if key.startswith('patent_file'):
            filename = secure_filename(f.filename)
            is_valid_file, msg, _, _ = validate_file(f, filename )
            if not is_valid_file:
               errors.append(filename + ' has error: '  + msg)
            else:
               f.save(os.path.join(app.config['UPLOADED_PATH'], patent_filename))
    if len(errors)>0:
      return ', '.join(errors), 400
  return render_template('index.html')

This works. But it shows the same error message across all files. I am looking for a way to send individual status message per file. Is this achievable through the plugin? Thanks in advance.

Other details:

$ pip show flask_dropzone
Name: Flask-Dropzone
Version: 1.5.4
Summary: Upload file in Flask with Dropzone.js.
Home-page: https://github.com/greyli/flask-dropzone
Requires: Flask
Required-by:
yuxiaoy1 commented 3 years ago

@skewwhiff The key is that you did not enable the parallel upload configuration, so there would be multiple requests for your multiple uploads, but you're handling the uploads in a way which there should only be one request for all the uploaded files.

And the solution is simple, handling the multiple file upload just the same as a single file upload, keep in mind that you should not enable the parallel upload specific to your need.

So the view function could be simplified something like below:

@app.route('<upload_url>', methods=['GET', 'POST'])
def file_upload():
    if request.method=='POST':
        f = request.files.get('patent_file')
        if f is None:
            return
        filename = secure_filename(f.filename)
        is_valid_file, msg, _, _ = validate_file(f, filename)
        if not is_valid_file:
            return f'{filename} has error: {msg}', 400
        f.save(os.path.join(app.config['UPLOADED_PATH'], patent_filename))
    return render_template('index.html')

Give it a try.