Introduction
In daily work, file upload is a common requirement. For example, collecting dump files generated by scripts when an application encounters an error for analysis, but implementing this feature can be quite complex. Fortunately, the Flask framework provides a simple and efficient way to handle file uploads, with less than 100 lines of code. In this article, we will explore how to implement file upload functionality using Flask, and write a Dockerfile to deploy the application via Docker.
Flask File Upload Process
The basic process of file upload in Flask includes the following steps:
- Create a
form with theenctype=multipart/form-dataattribute, and place aelement inside it. - The application accesses the file through the files dictionary of the request object.
- Use the file's
save()method to save the file to a location on the file system.
Implementing File Upload
Below is sample code for implementing file upload using Flask:
import os from flask import Flask, flash, request, redirect, url_for, send_from_directory from werkzeug.utils import secure_filenameUPLOAD_FOLDER = ‘/data/file_server/upload/’ # Path to store uploaded files
ALLOWED_EXTENSIONS = {‘txt’, ‘pdf’, ‘png’, ‘jpg’, ‘jpeg’, ‘gif’, ‘pcap’} # Allowed file extensions for uploadapp = Flask(name)
app.secret_key = ‘3ccfa213427578f707a015a87c5f94959df16cfd’
app.config[‘UPLOAD_FOLDER’] = UPLOAD_FOLDER# Check if the file extension is valid
def allowed_file(filename):
return ‘.’ in filename and
filename.rsplit(‘.’, 1)[1].lower() in ALLOWED_EXTENSIONS# Upload the file and redirect the user to the URL of the uploaded file
@app.route(‘/’, methods=[‘GET’, ‘POST’])
def upload_file():
if request.method == ‘POST’:
# Check if the request contains a file part
if ‘file’ not in request.files:
flash(‘No file part’)
return redirect(request.url)
file = request.files[‘file’]
# If the user does not select a file, the browser will still submit an empty file with no filename
if file.filename == ‘’:
flash(‘No selected file’)
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config[‘UPLOAD_FOLDER’], filename))
return redirect(url_for(‘uploaded_file’, filename=filename))
return ‘’’<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart form-data=“”>
<input type=file name=file>
<input type=submit value=upload>‘’’
# Provide a download link for uploaded files
@app.route(‘/uploads/<filename>’)
def uploaded_file(filename):
return send_from_directory(app.config[‘UPLOAD_FOLDER’], filename)
if name == ‘main’:
from waitress import serve
serve(app, host=“0.0.0.0”, port=9090)
</filename></input type=submit value=upload></input type=file name=file></form method=post enctype=multipart>
Security Considerations
When handling file uploads, security is an important consideration. For example, we do not want users to be able to upload any file type, as this could lead to cross-site scripting (XSS) attacks or other security issues. Therefore, the code logic adds a restriction on allowed file extension suffixes.
Additionally, the filename of uploaded files also requires consideration. The secure_filename() function is used to ensure filename security and prevent path traversal attacks. This function removes path information from the filename, leaving only the valid filename part. However, since the secure_filename function will omit Chinese characters when processing Chinese filenames, you should use English filenames.
Limiting Uploaded File Size
By default, Flask accepts file uploads of any size, but you can limit the maximum allowed file size by setting the MAX_CONTENT_LENGTH configuration key:
app.config['MAX_CONTENT_LENGTH'] = 16 * 1000 * 1000 # Limit to 16MB
This is generally used with an Nginx reverse proxy. You can control the maximum upload file size via Nginx's client_max_body_size directive.
Deploying the Application with Docker
Write the Dockerfile
FROM python:3WORKDIR /app/fileserver
RUN pip install flask Werkzeug waitress –index-url http://mirrors.cloud.aliyuncs.com/pypi/simple/ --trusted-host mirrors.cloud.aliyuncs.com
COPY fs.py ./
CMD [ “python”, “./fs.py” ]
Build the image
docker build -t flask-upload-app .
Start the container
docker run -d --name flask-upload-app -v /data/file_server/upload/:/data/file_server/upload/ -p 9090:9090 flask-upload-app
Configure Nginx reverse proxy
server {
listen 31503 ;
# Flask upload
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:9090/;
}
}
Testing the Upload
Conclusion
Following the steps above, you can easily implement file upload functionality by writing a Flask application. I hope this is helpful to everyone. If you have any questions, feel free to leave a comment to discuss, or follow my WeChat Official Account O&M Piglet (运维小猪), thank you!
References:
https://flask.palletsprojects.com/en/2.3.x/patterns/fileuploads/
This is a discussion topic separated from the original thread at https://juejin.cn/post/7368767452614017059
