How To Send Form Data With Files Using Python’s Flask and Dropzone.js
Pass multiple files with a web application
However, what if you want to add your Dropzone to an existing form and receive both files and form data with your Flask backend? This is a question I saw asked more than a few times online, so here’s a simple way to use Flask with Dropzone to send multiple files and form data with the click of a “Submit” button.
Why Would You Want To Send Files and Form Data Together?
There are a few reasons you might want to send files and form data together:
- If you want to send the files you’re collecting to an API, you might need to collect an API key, token, or something similar in order to complete an upload.
- If you want to associate the files with a person or data about the file, you might want to collect form data to do that.
- If you want to allow people to alter information about their file while sending. For example, maybe you want to offer them the chance to change the name of a file as they send it.
You’ll need to have a few things to get started:
- Python installed.
- Virtual environment for your project (optional but recommended).
- Flask installed.
- Requests installed.
- See the project on GitHub.
Note: This project is based on Miguel Grinberg’s Flask and Dropzone tutorial.
What’s in the HTML File?
For the sake of simplicity, I’ve created a simple form. Let’s go through the different parts of the HTML.
<form action="/" class="dropzone" id="my-dropzone" method="POST">
<label for="myFormData">Example Form Data</label>
<input type="text" name="myFormData" id="myFormData" placeholder="Enter your data" class="form-control" required/> </div>
I’ve included this snippet for reference. If you want to see everything together, please grab the code sample out of GitHub. You can see between the body tags that the form is doing a few things:
form action=“/”tells you where you want the information sent when you click the “Submit” button. You can include this information through a Dropzone configuration as well. I’m describing it here because an easy mistake is assuming Dropzone automatically knows where to send everything. It does if you specify using either Dropzone or, as I’ve selected, with the form action.
class=“dropzone”is how you let Dropzone know where you want to place a zone.
id=“my-dropzone”is what you need to reference the form and add your configuration options for Dropzone.
method=“POST”makes it clear you want to
POSTthe form data and file. If you leave this off, it will try to send your information with
GET, meaning the file will be left out.
The rest of the form is just setting up the “Submit” button and the fields you wanted. If you are wondering where the multipart setting is, you don’t need it here because you’re using Dropzone. Depending on what you decide to create, you may need to add it.
Up top between the
head tags, you can see all the different scripts and stylesheets you’ll need. Dropzone is flexible, so if you want to do things differently you can. You can also put the Dropzone
.css files into a static folder for Flask to find them. I opted to use CDNs for them instead.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.7.1/min/dropzone.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
Dropzone configuration script
You can place the configuration script for Dropzone in a few places, including in a separate file that you reference. I opted to add it under the dependencies in the HTML file using script tags. The configuration looks like this:
To set up, you have
myDropzone. This is a reference to your form, where you put the id as “my-dropzone.” Whatever name you choose, you put the name in camel case based on where you placed the dashes. So if you have “my-amazing-dropzone,” it would be
myAmazingDropzone. For the options, you set these:
false. This tells Dropzone not to automatically grab your files and send them away.
true. If you want to be able to drag-and-drop a bunch of files at once, you need this set to
10because I think testing it out with ten is probably enough for this walkthrough. This is how many files will try to upload at the same time.
maxFilesis for how many files you want someone to be able to drop at once. I put
Next, we add an event listener to our “Submit” button. We can reference it by the type of button it is, so an ID isn’t needed. Then we tell Dropzone to upload everything when the “Submit” button is clicked. That’s it for the form. Let’s go take a look at
What’s in the app.py File?
The code for
app.py looks like this (for the full code, please go to the sample on GitHub):
from flask import Flask, render_template, request, redirect, url_for, abort
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config['UPLOAD_EXTENSIONS'] = ['.mov', '.mp4', '.m4v', '.jpm', '.jp2', '.3gp', '.3g2', '.mkv', '.mpg', '.ogv', '.webm', '.wmv' ]
app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024
return "File is too large", 413
my_files = request.files
formData = request.form['myFormData']
with open("my_data.txt", "x+") as my_data:
for item in my_files:
uploaded_file = my_files.get(item)
uploaded_file.filename = secure_filename(uploaded_file.filename)
if uploaded_file.filename != '':
file_ext = os.path.splitext(uploaded_file.filename)
if file_ext not in app.config['UPLOAD_EXTENSIONS']:
You can read a detailed discussion about this code in Grinberg’s tutorial. The changes I made here were:
- Making this sample about video. For upload extensions, I only made it possible to upload videos. You can change that to be for text files or images. Or if you aren’t worried about securing your files at all, you can get rid of the upload extensions configuration.
- Making it possible to process form data alongside files. The important thing to note is that your files and forms are in two different parts of the request information.
request.formis going to contain all the fields you added, and
request.fileswill have your file information. Files are in an immutable multi-dictionary.
- Keeping the
filesobject. Instead of taking the filename out of the item in
my_files, you can see I just update the filename in the item.
- Adding a spot where I take the form data and write it to a text file. You can do lots of other things like add a database or process this information some other way. This was just to provide a simple example. By the way, all the files are stored in the same directory in this example.
You may want to go over Grinberg’s tutorial if you’re handling images and want thumbnails, as he presents a way to do that. It’s also a useful tutorial if you want to read about the various security features in the code snippet.
Depending on the size of your files, you might want to change the
MAX_CONTENT_LENGTH configuration to accept bigger files instead of just
1024 * 1024.
You can also find more Dropzone information on the Dropzone.js site. I hope this helped you get started with using Dropzone with multiple files and form data!
Developer Advocate and Comedian