使用 Python Flask 創(chuàng)建簡易文件上傳服務(wù)(flask實現(xiàn)文件上傳)
引言
在平時工作中,文件上傳是一項常見的需求,例如將應(yīng)用異常時通過腳本生成的dump文件收集起來進(jìn)行分析,但實現(xiàn)起來卻可能相當(dāng)復(fù)雜。幸運的是,Flask框架提供了一種簡單而高效的方式來處理文件上傳,代碼不到100行。在本文中,我們將探討如何使用Flask實現(xiàn)文件上傳功能,編寫dockerfile將應(yīng)用程序通過Docker部署。
Flask 文件上傳流程
Flask文件上傳的基本流程包括以下幾個步驟:
- 創(chuàng)建一個帶有 enctype=multipart/form-data 屬性的 <form> 表單,并在其中放置一個 <input type=file> 元素。
- 應(yīng)用程序通過請求對象的 files 字典訪問文件。
- 使用文件的 save() 方法將文件保存到文件系統(tǒng)的某個位置。
實現(xiàn)文件上傳
以下是使用Flask實現(xiàn)文件上傳的示例代碼:
# coding:utf-8import osfrom flask import Flask, flash, request, redirect, url_for, send_from_directoryfrom werkzeug.utils import secure_filenameUPLOAD_FOLDER = '/data/file_server/upload/' # 上傳文件存儲的路徑ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'pcap'} # 允許上傳的文件擴(kuò)展名app = Flask(__name__)app.secret_key = '3ccfa213427578f707a015a87c5f94959df16cfd'app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER# 檢查文件擴(kuò)展名是否合法def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS# 上傳文件并重定向用戶到上傳后的文件URL@app.route('/', methods=['GET', 'POST'])def upload_file(): if request.method == 'POST': # 檢查請求中是否包含文件部分 if 'file' not in request.files: flash('No file part') return redirect(request.url) file = request.files['file'] # 如果用戶沒有選擇文件,瀏覽器也會提交一個沒有文件名的空文件 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 ''' <!doctype html> <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> </form> '''# 提供已上傳文件的下載鏈接@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)
安全性考量
在處理文件上傳時,安全性是一個重要的考慮因素。例如,我們不希望用戶能夠上傳任何文件類型,因為這可能導(dǎo)致跨站腳本攻擊(XSS)或其他安全問題。因此代碼邏輯加上限制允許上傳的文件擴(kuò)展名后綴。
另外對于上傳文件的文件名也是需要考慮的,secure_filename() 函數(shù)用于確保文件名的安全,防止路徑穿越攻擊。該函數(shù)會移除文件名中的路徑信息,只保留有效的文件名部分。不過由于secure_filename函數(shù)獲取中文文件名時,中文會被省略,所以文件名都要使用英文格式。
secure_filename()函數(shù)
限制上傳文件大小
Flask 默認(rèn)情況下會接受任意大小的文件上傳,但可以通過設(shè)置 MAX_CONTENT_LENGTH 配置鍵來限制最大允許的文件大?。?/span>
app.config['MAX_CONTENT_LENGTH'] = 16 * 1000 * 1000 # 限制為16MB
一般會搭配nginx反向代理來使用,可以通過Nginx的 client_max_body_size 指令控制上傳文件大小。
Docker部署應(yīng)用
編寫Dockerfile
FROM python:3WORKDIR /app/fileserverRUN pip install flask Werkzeug waitress --index-url http://mirrors.cloud.aliyuncs.com/pypi/simple/ --trusted-host mirrors.cloud.aliyuncs.comCOPY fs.py ./CMD [ "python", "./fs.py" ]
構(gòu)建鏡像
docker build -t flask-upload-app .
啟動容器
docker run -d --name flask-upload-app -v /data/file_server/upload/:/data/file_server/upload/ -p 9090:9090 flask-upload-app
配置Nginx反向代理
server { listen 31503 ; # flask上傳 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/; }}
測試上傳
結(jié)語
通過上述步驟,你可以編寫Flask應(yīng)用輕松實現(xiàn)文件上傳功能,希望對大家有所幫助。如果你還有任何疑問,歡迎留言討論,或者關(guān)注我的微信公眾號運維小豬,謝謝!
參考鏈接:
https://flask.palletsprojects.com/en/2.3.x/patterns/fileuploads/