Flask文件上传
https://zhuanlan.zhihu.com/p/23731819
Flask文件上傳(一):原生實現
李輝
greyli.com
87 人贊同了該文章
文件上傳是個躲不掉的問題,用戶頭像,文章圖片,文件分享等等都需要上傳功能。但這里涉及很多內容,上傳文件,過濾文件類型,限制大小,上傳前的編輯篩選,拖拽上傳,進度條,文件命名,文件目錄管理,訪問速度……
盡管有一些庫和插件來簡化這個過程,但還是很麻煩,如果沒有太多時間和精力,或是有很大的上傳需求,就不要跳坑了。這一切可以花錢解決:文件可以用各種網盤;圖片使用各種圖床,速度快而且功能齊全,你只需要集成上傳接口;
因為內容很多,我打算用三到四篇文章來寫這個主題。這篇文章介紹用Flask原生實現上傳和一些基礎內容。
?
?
Flask文件上傳系列目錄
?
?
?
使用Flask原生實現文件上傳
簡單來說,只有三個步驟:
1、創建一個上傳表單:
<form method="POST" enctype="multipart/form-data"><input type="file" name="file"><input type="submit" value="Upload"> </form>2、當按下提交鍵后,通過request對象上的files獲取文件。和以前用request獲取表單值一樣,使用input字段的name值獲取:
file = request.files['file']3、使用save()方法保存文件,指定保存的地址及文件名:
file.save(path + filename)當然,除了這些,還有很多東西要考慮。
?
?
上傳配置
在這里我們設置上傳文件夾地址、允許的文件擴展名、限制文件大小:
UPLOAD_FOLDER = '/path/to/the/uploads' ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif']) MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # 16MB你也可以使用:
app.config['UPLOAD_FOLDER'] = '/path/to/the/uploads'Flask配置介紹見這篇文章。
?
?
安全問題
1、導入Werkzeug提供的secure_filename()函數來檢查文件名:
filename = secure_filename(file.filename) 要注意的是,secure_filename僅返回ASCII字符。所以, 非ASCII(比如漢字)會被過濾掉,空格會被替換為下劃線。你也可以自己處理文件名,或是在使用這個函數前將中文替換為拼音或是英文。具體見后續文章。2、使用我們在上面配置的擴展名來檢查文件類型。
創建一個檢查函數:
def allowed_file(filename):return '.' in filename and \filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS判斷上傳文件名:
... if file and allowed_file(file.filename): ...3、使用上面配置的文件最大長度來檢查文件大小(僅需要配置),如果超過限制,會拋出RequestEntityTooLarge異常,進而返回413錯誤(在開發服務器可能會直接斷開連接,屬正常現象)。
?
?
獲取上傳后的文件
配置一個函數來獲取上傳文件的url:
from flask import send_from_directory@app.route('/uploads/<filename>') def uploaded_file(filename):return send_from_directory(app.config['UPLOAD_FOLDER'],filename)獲取url:
file_url = url_for('uploaded_file', filename=filename)?
完整的實現
這是一個圖片上傳Demo,你可以復制或是在Github上下載體驗一下。
# -*- coding: utf-8 -*- import os from flask import Flask, request, url_for, send_from_directory from werkzeug import secure_filenameALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])app = Flask(__name__) app.config['UPLOAD_FOLDER'] = os.getcwd() app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024html = '''<!DOCTYPE html><title>Upload File</title><h1>圖片上傳</h1><form method=post enctype=multipart/form-data><input type=file name=file><input type=submit value=上傳></form>'''def allowed_file(filename):return '.' in filename and \filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS@app.route('/uploads/<filename>') def uploaded_file(filename):return send_from_directory(app.config['UPLOAD_FOLDER'],filename)@app.route('/', methods=['GET', 'POST']) def upload_file():if request.method == 'POST':file = request.files['file']if file and allowed_file(file.filename):filename = secure_filename(file.filename)file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))file_url = url_for('uploaded_file', filename=filename)return html + '<br><img src=' + file_url + '>'return htmlif __name__ == '__main__':app.run()Gist地址:https://gist.github.com/greyli/a643aaac06ea8c23769c0c3d9ccaae79
?
?
相關鏈接
- request對象:http://flask.pocoo.org/docs/0.11/api/#incoming-request-data
- Flask文檔,文件上傳:http://flask.pocoo.org/docs/0.11/patterns/fileuploads/
?
- - - - -
更多關于Flask和Web開發的原創內容,歡迎關注知乎專欄 - Hello, Flask!。
總結
- 上一篇: unix高级编程apue.h问题
- 下一篇: 查询手机号码归属地区等信息API接口