Flask-Uploads allows your application to flexibly and efficiently handle file uploading and serving the uploaded files. You can create different sets of uploads - one for document attachments, one for photos, etc. - and the application can be configured to save them all in different places and to generate different URLs for them.
If you’re just deploying an application that uses Flask-Uploads, you can customize its behavior extensively from the application’s configuration. Check the application’s documentation or source code to see how it loads its configuration.
The settings below apply for a single set of uploads, replacing FILES with the name of the set (i.e. PHOTOS, ATTACHMENTS):
However, to save on configuration time, there are two settings you can provide that apply as “defaults” if you don’t provide the proper settings otherwise.
However, you don’t have to set any of the _URL settings - if you don’t, then they will be served internally by Flask. They are just there so if you have heavy upload traffic, you can have a faster production server like Nginx or Lighttpd serve the uploads.
An “upload set” is a single collection of files. You just declare them in the code:
photos = UploadSet('photos', IMAGES)
And then you can use the save method to save uploaded files and path and url to access them. For example:
@app.route('/upload', methods=['GET', 'POST'])
def upload():
if request.method == 'POST' and 'photo' in request.files:
filename = photos.save(request.files['photo'])
rec = Photo(filename=filename, user=g.user.id)
rec.store()
flash("Photo saved.")
return redirect(url_for('show', id=rec.id))
return render_template('upload.html')
@app.route('/photo/<id>')
def show(id):
photo = Photo.load(id)
if photo is None:
abort(404)
url = photos.url(photo.filename)
return render_template('show.html', url=url, photo=photo)
If you have a “default location” for storing uploads - for example, if your app has an “instance” directory like Zine and uploads should be saved to the instance directory’s uploads folder - you can pass a default_dest callable to the set constructor. It takes the application as its argument. For example:
media = UploadSet('media', default_dest=lambda app: app.instance_root)
This won’t prevent a different destination from being set in the config, though. It’s just to save your users a little configuration time.
An upload set’s configuration is stored on an app. That way, you can have upload sets being used by multiple apps at once. You use the configure_uploads function to load the configuration for the upload sets. You pass in the app and all of the upload sets you want configured. Calling configure_uploads more than once is safe.
configure_uploads(app, (photos, media))
If your app has a factory function, that is a good place to place this call.
In addition, you can also use patch_request_class to patch your app’s request_class to have a maximum size for uploads. By default, there is no limit, so it’s possible for script kiddies to crash your server by uploading gigantic files. Calling it will install a limit that prevents it from loading more than a certain amount of data.
patch_request_class(app) # 16 megabytes
patch_request_class(app, 32 * 1024 * 1024)
# 32 megabytes
If you need to upload huge files, you may want to look into another solution like rsync.
To actually upload the files, you need to properly set up your form. A form that uploads files needs to have its method set to POST and its enctype set to multipart/form-data. If it’s set to GET, it won’t work at all, and if you don’t set the enctype, only the filename will be transferred.
The field itself should be an <input type=file>.
<form method=POST enctype=multipart/form-data action="{{ url_for('upload') }}">
...
<input type=file name=photo>
...
</form>
Here are the API docs. These are generated directly from the source code.
This represents a single set of uploaded files. Each upload set is independent of the others. This can be reused across multiple application instances, as all configuration is stored on the application object itself and found with flask.current_app.
Parameters: |
|
---|
This gets the current configuration. By default, it looks up the current application and gets the configuration from there. But if you don’t want to go to the full effort of setting an application, or it’s otherwise outside of a request context, set the _config attribute to an UploadConfiguration instance, then set it back to None when you’re done.
This determines whether a specific extension is allowed. It is called by file_allowed, so if you override that but still want to check extensions, call back into this.
Parameters: |
|
---|
This tells whether a file is allowed. It should return True if the given werkzeug.FileStorage object can be saved with the given basename, and False if it can’t. The default implementation just checks the extension, so you can override this if you want.
Parameters: |
|
---|
This returns the absolute path of a file uploaded to this set. It doesn’t actually check whether said file exists.
Parameters: |
|
---|
If a file with the selected name already exists in the target folder, this method is called to resolve the conflict. It should return a new basename for the file.
The default implementation splits the name and extension and adds a suffix to the name consisting of an underscore and a number, and tries that until it finds one that doesn’t exist.
Parameters: |
|
---|
This saves a werkzeug.FileStorage into this upload set. If the upload is not allowed, an UploadNotAllowed error will be raised. Otherwise, the file will be saved and its name (including the folder) will be returned.
Parameters: |
|
---|
This function gets the URL a file uploaded to this set would be accessed at. It doesn’t check whether said file exists.
Parameters: |
|
---|
This holds the configuration for a single UploadSet. The constructor’s arguments are also the attributes.
Parameters: |
|
---|
Call this after the app has been configured. It will go through all the upload sets, get their configuration, and store the configuration on the app. It will also register the uploads module if it hasn’t been set.
Parameters: |
---|
By default, Flask will accept uploads to an arbitrary size. Unfortunately, this could lead to a security hole: someone uploads a gigantic file, and crashes your server when it runs out of memory. Calling this on an application will patch the app’s request class so that when it hits a certain size, it will automatically raise an HTTP error.
Parameters: |
|
---|
These are some default sets of extensions you can pass to the UploadSet constructor.
This can be used to allow all file types except certain ones. For example, to ban .exe and .iso files, pass:
AllExcept(('exe', 'iso'))
to the UploadSet constructor as extensions. You can use any container, for example:
AllExcept(SCRIPTS + EXECUTABLES)
This “contains” all items. You can use it to allow all extensions to be uploaded.
This just contains plain text files (.txt).
This contains basic image types that are viewable from most browsers (.jpg, .jpe, .jpeg, .png, .gif, .svg, and .bmp).
This contains audio file types (.wav, .mp3, .aac, .ogg, .oga, and .flac).
This contains various office document formats (.rtf, .odf, .ods, .gnumeric, .abw, .doc, .docx, .xls, and .xlsx). Note that the macro-enabled versions of Microsoft Office 2007 files are not included.
This is for structured data files (.csv, .ini, .json, .plist, .xml, .yaml, and .yml).
This contains various types of scripts (.js, .php, .pl, .py .rb, and .sh). If your Web server has PHP installed and set to auto-run, you might want to add php to the DENY setting.
This contains archive and compression formats (.gz, .bz2, .zip, .tar, .tgz, .txz, and .7z).
This is a helper for testing upload behavior in your application. You can manually create it, and its save method is overloaded to set saved to the name of the file it was saved to. All of these parameters are optional, so only bother setting the ones relevant to your application.
Parameters: |
|
---|