Python: Using Flask to upload files

python-logoIf you are looking for basic HTTP file uploading using Flask, you can use the code in my python-flask-upload-files project on github as an example.

This project exercises multiple scenarios:

  • Upload a single file in chunked mode (not forced to save entirety to disk)
  • Upload a single file
  • Upload multiple files
  • Error message shown when submitted as GET
  • Error message shown when submitted as POST, but no file element sent

Prerequisites

You will need the Flask library installed to run this test.

sudo pip install Flask
# If using Ubuntu16 
sudo pip3 install Flask

Example Code

I have uploaded a sample Python Flask application to github, flask_upload_files.py.  This sample application receives an upload from the browser of either a single file or multiple files.

# download entire project
git clone https://github.com/fabianlee/python-flask-upload-files.git
cd python-flask-upload-files

# run streaming Flask app on port 8080
python3 ./flask_upload_files.py

Upon startup, the ‘tempdir’ will be written to the console, which is where the uploaded files will be saved.

Manual testing

The application should now be running on port 8080, and you can open your browser to the URL below, which will provide a graphical test harness for the upload scenarios listed above.

http://localhost:8080/upload_form

Go ahead and pick a local file(s) to upload, and they will end up in your tempdir.  When you downloaded the project, there was a “tests” directory created which has jpg and pdf files that can be used.

Take note that only the following extensions are allowed by default in the code.

ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])

Automated testing

You do not have to necessarily use a browser to test these upload scenarios.  You can also use a script or utility such as curl.

Here is an example of uploading a single file:

curl -X POST http://localhost:8080/multipleupload -F "files[]=@tests/car.jpg"

And here of uploading multiple files:

curl -X POST http://localhost:8080/multipleupload -F "files[]=@tests/car.jpg" -F "files[]=@tests/testdoc.pdf"

Chunked upload

Notice that the single file, chunked upload scenario does not access any of the other request attribute such as form fields.  If it did, the Flask framework would materialize the file in its entirety in either memory/disk.

 

REFERENCES

palltestproject, file uploads

palletsproject, datastructures

flask docs, request object

keithwatanabe, flask needs secret for flashing

izmailoff, describes how flask can stream upload but only if not touching form/file objects

stackoverflow, pip freeze

viveksb007, uploading/downloading using flask

dustindavignon, using dropzone for more advanced uploads using flask

roytuts, uploading files with flask