Flask文件上传
https://zhuanlan.zhihu.com/p/23731819
Flask文件上傳(一):原生實(shí)現(xiàn)
李輝
greyli.com
87 人贊同了該文章
文件上傳是個(gè)躲不掉的問題,用戶頭像,文章圖片,文件分享等等都需要上傳功能。但這里涉及很多內(nèi)容,上傳文件,過濾文件類型,限制大小,上傳前的編輯篩選,拖拽上傳,進(jìn)度條,文件命名,文件目錄管理,訪問速度……
盡管有一些庫和插件來簡化這個(gè)過程,但還是很麻煩,如果沒有太多時(shí)間和精力,或是有很大的上傳需求,就不要跳坑了。這一切可以花錢解決:文件可以用各種網(wǎng)盤;圖片使用各種圖床,速度快而且功能齊全,你只需要集成上傳接口;
因?yàn)閮?nèi)容很多,我打算用三到四篇文章來寫這個(gè)主題。這篇文章介紹用Flask原生實(shí)現(xiàn)上傳和一些基礎(chǔ)內(nèi)容。
?
?
Flask文件上傳系列目錄
?
?
?
使用Flask原生實(shí)現(xiàn)文件上傳
簡單來說,只有三個(gè)步驟:
1、創(chuàng)建一個(gè)上傳表單:
<form method="POST" enctype="multipart/form-data"><input type="file" name="file"><input type="submit" value="Upload"> </form>2、當(dāng)按下提交鍵后,通過request對(duì)象上的files獲取文件。和以前用request獲取表單值一樣,使用input字段的name值獲取:
file = request.files['file']3、使用save()方法保存文件,指定保存的地址及文件名:
file.save(path + filename)當(dāng)然,除了這些,還有很多東西要考慮。
?
?
上傳配置
在這里我們?cè)O(shè)置上傳文件夾地址、允許的文件擴(kuò)展名、限制文件大小:
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、導(dǎo)入Werkzeug提供的secure_filename()函數(shù)來檢查文件名:
filename = secure_filename(file.filename) 要注意的是,secure_filename僅返回ASCII字符。所以, 非ASCII(比如漢字)會(huì)被過濾掉,空格會(huì)被替換為下劃線。你也可以自己處理文件名,或是在使用這個(gè)函數(shù)前將中文替換為拼音或是英文。具體見后續(xù)文章。2、使用我們?cè)谏厦媾渲玫臄U(kuò)展名來檢查文件類型。
創(chuàng)建一個(gè)檢查函數(shù):
def allowed_file(filename):return '.' in filename and \filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS判斷上傳文件名:
... if file and allowed_file(file.filename): ...3、使用上面配置的文件最大長度來檢查文件大小(僅需要配置),如果超過限制,會(huì)拋出RequestEntityTooLarge異常,進(jìn)而返回413錯(cuò)誤(在開發(fā)服務(wù)器可能會(huì)直接斷開連接,屬正常現(xiàn)象)。
?
?
獲取上傳后的文件
配置一個(gè)函數(shù)來獲取上傳文件的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)?
完整的實(shí)現(xiàn)
這是一個(gè)圖片上傳Demo,你可以復(fù)制或是在Github上下載體驗(yàn)一下。
# -*- 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
?
?
相關(guān)鏈接
- request對(duì)象:http://flask.pocoo.org/docs/0.11/api/#incoming-request-data
- Flask文檔,文件上傳:http://flask.pocoo.org/docs/0.11/patterns/fileuploads/
?
- - - - -
更多關(guān)于Flask和Web開發(fā)的原創(chuàng)內(nèi)容,歡迎關(guān)注知乎專欄 - Hello, Flask!。
總結(jié)
- 上一篇: unix高级编程apue.h问题
- 下一篇: 查询手机号码归属地区等信息API接口