Nowadays, almost every web platform enables file uploads. From Facebook, Twitter, and Instagram to Indeed, LinkedIn, and Coursera, thousands of websites and web apps allow users to upload images, videos, documents, portfolios, CVs, etc. However, implementing the file upload functionality can sometimes be challenging for developers.
For example, developers have to ensure the file uploader is user-friendly and aesthetically appealing. They also need to enable multiple file uploads. Another essential point to consider while creating a file uploader is to ensure secure file uploads.
Otherwise, cyber attackers can deploy viruses by uploading malicious files or files that are too large in size. That’s why many developers now use a third-party file uploader, such as React image upload SDK, Angular file uploader, JS file uploader, etc.
However, you can also build a secure and fast file uploader. If you’re using Flask to build your web apps, you can follow this guide/tutorial to implement a secure file uploader.
Built by Armin Ronacher, Flask is essentially a web framework that is written in Python. A web framework refers to a set of libraries and modules that makes it quick and easy for developers to create web apps as they don’t have to worry about thread management, protocol, and other low-level details.
When it comes to Python, the two most common options are Flask and Django. While Flask is a micro framework, Django is a high-level web framework.
However, many developers, especially beginners, prefer Flask as it’s easier to learn and use. Additionally, it is quicker to build apps using Flask as it keeps the core of the apps scalable and simple. You can also easily extend its functionality.
File upload is simply a form of user input. This means a user uploads a file, such as a single image, multiple images, documents, etc., using a file uploader. While a file uploader is simply an upload button or drag-and-drop interface for end-users, it is much more than that for developers. They need to focus on several features while creating a file uploader.
For example, they need to ensure the file uploader validates the file size, name, and format, allows users to upload multiple images or files, shows an image preview, and more. Once the files are successfully uploaded, a file uploader should send them to the server.
For regular forms, the submitted form files can be found in the ‘request.form’ dictionary. When it comes to file fields, you can access the ‘request.files’ dictionary. Both dictionaries support duplicate keys as they are “multi-dicts.” This is a useful feature because forms can have more than one field with the same name. The same goes for file fields that accept more than one file.
When a user uploads a file, it is treated like any other form submission. So, you need to define an HTML form containing a file field.
<!doctype html>
<html>
<head>
<title>File Upload</title>
</head>
<body>
<h1>File Upload</h1>
<form method=“POST” action=“” enctype=“multipart/form-data”>
<p><input type=“file” name=“file”></p>
<p><input type=“submit” value=“Submit”></p>
</form>
</body>
</html>
The following example code shows a flask app that accepts file uploads:
from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)
@app.route(‘/’)
def index():
return render_template(‘index.html’)
@app.route(‘/’, methods=[‘POST’])
def upload_file():
uploaded_file = request.files[‘file’]
if uploaded_file.filename != ”:
uploaded_file.save(uploaded_file.filename)
return redirect(url_for(‘index’))
Before we show you how to implement secure file uploads with Flask, let’s first discuss the importance of secure file uploads.
Sometimes cyber attackers take advantage of the file upload feature on your website or web app to deploy viruses and upload malicious files. Additionally, they can upload a file that is too large in size, causing the server to malfunction. Cyber Attackers can also rewrite system configuration files by uploading images of files with suspicious names.
That’s why it’s crucial to validate files before uploading them to the server and set a limit for file sizes. For example, when you’re using Flask, you can utilize the Flask-WTF extension to validate all the form fields. Similarly, it’s essential to validate file uploads or file fields.
Here is how you can secure file uploads with Flask:
A simple and easy way to validate the file name is to see if your app supports the file extension.
import os
from flask import Flask, render_template, request, redirect, url_for, abort
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config[‘MAX_CONTENT_LENGTH’] = 1024 * 1024
app.config[‘UPLOAD_EXTENSIONS’] = [‘.jpg’, ‘.png’, ‘.gif’]
app.config[‘UPLOAD_PATH’] = ‘uploads’
@app.route(‘/’)
def index():
return render_template(‘index.html’)
@app.route(‘/’, methods=[‘POST’])
def upload_files():
uploaded_file = request.files[‘file’]
filename = secure_filename(uploaded_file.filename)
if filename != ”:
file_ext = os.path.splitext(filename)[1]
if file_ext not in app.config[‘UPLOAD_EXTENSIONS’]:
abort(400)
uploaded_file.save(os.path.join(app.config[‘UPLOAD_PATH’], filename))
return redirect(url_for(‘index’))
If your app accepts only certain file types, it’s essential to validate file content. If a user uploads a file type that your app doesn’t support, it should instantly reject those files.
import imghdr
def validate_image(stream):
header = stream.read(512)
stream.seek(0)
format = imghdr.what(None, header)
if not format:
return None
return ‘.’ + (format if format != ‘jpeg’ else ‘jpg’)
Here is the complete code for validating file content:
import imghdr
import os
from flask import Flask, render_template, request, redirect, url_for, abort
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config[‘MAX_CONTENT_LENGTH’] = 1024 * 1024
app.config[‘UPLOAD_EXTENSIONS’] = [‘.jpg’, ‘.png’, ‘.gif’]
app.config[‘UPLOAD_PATH’] = ‘uploads’
def validate_image(stream):
header = stream.read(512)
stream.seek(0)
format = imghdr.what(None, header)
if not format:
return None
return ‘.’ + (format if format != ‘jpeg’ else ‘jpg’)
@app.route(‘/’)
def index():
return render_template(‘index.html’)
@app.route(‘/’, methods=[‘POST’])
def upload_files():
uploaded_file = request.files[‘file’]
filename = secure_filename(uploaded_file.filename)
if filename != ”:
file_ext = os.path.splitext(filename)[1]
if file_ext not in app.config[‘UPLOAD_EXTENSIONS’] or \
file_ext != validate_image(uploaded_file.stream):
abort(400)
uploaded_file.save(os.path.join(app.config[‘UPLOAD_PATH’], filename))
return redirect(url_for(‘index’))
Flask offers a configuration option called ‘MAX_CONTENT_LENGTH’ that is helpful in preventing users from uploading large files. This configuration defines the maximum size of a request body.
app.config[‘MAX_CONTENT_LENGTH’] = 1024 * 1024
Once users upload files, they can be used for public or private purposes, depending on the type of app. For example, some applications utilize the uploaded files for internal processes, so no further action is required. However, for some apps, you need to integrate the files into the app.
When users upload files or images on sites like Facebook and Twitter, such as display pictures, you need to make them available for public use by the app. This can be achieved by placing the upload directory inside the app’s static folder.
import imghdr
import os
from flask import Flask, render_template, request, redirect, url_for, abort, \
send_from_directory
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config[‘MAX_CONTENT_LENGTH’] = 1024 * 1024
app.config[‘UPLOAD_EXTENSIONS’] = [‘.jpg’, ‘.png’, ‘.gif’]
app.config[‘UPLOAD_PATH’] = ‘uploads’
def validate_image(stream):
header = stream.read(512) # 512 bytes should be enough for a header check
stream.seek(0) # reset stream pointer
format = imghdr.what(None, header)
if not format:
return None
return ‘.’ + (format if format != ‘jpeg’ else ‘jpg’)
@app.route(‘/’)
def index():
files = os.listdir(app.config[‘UPLOAD_PATH’])
return render_template(‘index.html’, files=files)
@app.route(‘/’, methods=[‘POST’])
def upload_files():
uploaded_file = request.files[‘file’]
filename = secure_filename(uploaded_file.filename)
if filename != ”:
file_ext = os.path.splitext(filename)[1]
if file_ext not in app.config[‘UPLOAD_EXTENSIONS’] or \
file_ext != validate_image(uploaded_file.stream):
abort(400)
uploaded_file.save(os.path.join(app.config[‘UPLOAD_PATH’], filename))
return redirect(url_for(‘index’))
@app.route(‘/uploads/<filename>’)
def upload(filename):
return send_from_directory(app.config[‘UPLOAD_PATH’], filename)
Some files uploaded by users are not for public use, such as when a user uploads an image on an online image editing app. Such apps must ensure that only the authorized user can access certain files.
@app.route(‘/uploads/<filename>’)
@login_required
def upload(filename):
return send_from_directory(os.path.join(
app.config[‘UPLOAD_PATH’], current_user.get_id()), filename)
If you find it challenging to build a file uploader from scratch, you can use a third-party tool like Filestack file uploader and file upload API. For example, Filestack File Picker allows you to implement a fast, secure, and user-friendly file uploader in your apps super quickly.
You can configure and customize the File Picker the way you want, and it can also integrate with popular data storage solutions like Dropbox and Google Drive and social media services like Facebook and Instagram. Additionally, developers can also access the underlying API via different SDKs, such as Python File upload SDK.
You can also use the Filestack File API for uploading files over HTTP. For example, you can directly upload a file, or you can upload a file from a URL via an HTTP request. It also supports multipart uploads.
Allowing users to upload files like documents, videos, and image upload is a basic requirement of many web apps and websites. However, developers need to focus on several aspects to build an efficient file uploader.
For example, they need to enable multiple file uploads, preview images, send uploaded files to the server, and more. If you’re using Flask Python to build your web apps, you can follow this guide to build an efficient and secure file uploader for your apps. If you don’t want to build a file uploader from scratch, you can also use a third-party tool.
File uploads mean allowing users to upload files, such as images, documents, and videos, on your website or web app. However, once the files are uploaded, we need to send them to the server. A file uploader can be a simple upload button for end-users, or it can be a drag-and-drop interface.
Secure file uploads are important because cyber attackers can upload malicious files and deploy viruses in your system. Additionally, they can upload files that are too large or use suspicious file names. You can enable secure file uploads by validating file name, size, and type.
Flask is an easy-to-use web framework for building apps with Python quickly. You can implement file upload functionality in Flask quickly by following this guide. Or you can use a third-party Python file upload SDK to add a file uploader to your app with a few lines of code.
Building a robust online presence is no longer optional for entrepreneurs; it’s a necessity. Websites… Read More
Advanced application security testing tools are key to the rapid pace of digital transformation. Applications… Read More
Endpoint management is a superhero today. It caters to various requirements of an organization. These… Read More
Today, it is impossible to conduct business by ignoring the online presence; therefore, it is… Read More
Simply put, supply chains are the cornerstone of modern businesses. They effectively connect organizations not… Read More
AI is transforming customer service by making it quicker and more intelligent. Chatbots and AI… Read More