Flask文件上傳(三):完整實現

在上篇文章里,我們使用擴展簡化了文件上傳的步驟。這次使用Flask-WTF來增強表單功能:處理表單驗證,顯示錯誤信息。因為同時使用Flask-Uploads,上傳部分的實現見前兩篇文章。

Flask文件上傳系列目錄

  1. Flask文件上傳(一):原生實現

  2. Flask文件上傳(二):使用擴展實現

  3. Flask文件上傳(三):完整實現

  4. Flask文件上傳(四):文件管理與多文件上傳
  5. Flask文件上傳(五):拖拽上傳和進度條

使用Flask-WTF

如果你對Flask-WTF還不熟悉,可以看看之前的幾篇文章,或是讀讀文檔。

1、初始化

為CSRF保護創建SECRET_KEY設置:

app.config[SECRET_KEY] = a random stringn

2、創建表單

使用Flask-WTF提供的FileField欄位以及FileRequiredFileAllowed驗證函數

from flask_wtf.file import FileField, FileRequired, FileAllowedn

可以傳入錯誤信息:

photo = FileField(u圖片上傳, validators=[n FileAllowed(photos, u只能上傳圖片!), n FileRequired(u文件未選擇!)n])n

這裡FileAllowed()的第一個參數是使用Flask-Uploads設置的set名稱,如果不使用Flask-Uploads,可以替換成文件後綴組成的列表,比如[jpg, png]。

3、在模板中渲染錯誤信息

{% for error in form.field.errors %}n {{ error }}n{% endfor %}n

這裡面的field是欄位名稱,比如上面的photo。

4、獲取文件

文件數據不再從request對象獲取,而是使用data方法獲取:

filename = photos.save(form.photo.data)n

完整實現

這次把HTML代碼放在了單獨的文件,效果仍然和之前兩個版本相同。

upload.py

# -*- coding: utf-8 -*-nimport osnnfrom flask import Flask, render_templatenfrom flask_uploads import UploadSet, configure_uploads, IMAGES, patch_request_classnfrom flask_wtf import FlaskFormnfrom flask_wtf.file import FileField, FileRequired, FileAllowednfrom wtforms import SubmitFieldnnapp = Flask(__name__)napp.config[SECRET_KEY] = I have a dreamnapp.config[UPLOADED_PHOTOS_DEST] = os.getcwd()nnphotos = UploadSet(photos, IMAGES)nconfigure_uploads(app, photos)npatch_request_class(app) # set maximum file size, default is 16MBnnnclass UploadForm(FlaskForm):n photo = FileField(validators=[n FileAllowed(photos, u只能上傳圖片!), n FileRequired(u文件未選擇!)])n submit = SubmitField(u上傳)nnn@app.route(/, methods=[GET, POST])ndef upload_file():n form = UploadForm()n if form.validate_on_submit():n filename = photos.save(form.photo.data)n file_url = photos.url(filename)n else:n file_url = Nonen return render_template(index.html, form=form, file_url=file_url)nnnif __name__ == __main__:n app.run()n

模板文件:index.html

<!DOCTYPE html>n<title>Upload File</title>n<h1>圖片上傳</h1>n<form method="POST" enctype="multipart/form-data">n {{ form.hidden_tag() }}n {{ form.photo }}n {% for error in form.photo.errors %}n <span stylex="color: red;">{{ error }}</span>n {% endfor %}n {{ form.submit }}n</form>nn{% if file_url %}n<br><img src="{{ file_url }}">n{% endif %}n

Gist地址:gist.github.com/greyli/

文件在資料庫的表示

肯定有人想把文件存到資料庫里,胡亂試了一通後發現沒法子。甚至還有人想要把文件轉換成base64編碼存起來。這不是一心想把資料庫玩壞么……資料庫不是用來存文件的,文件應該放到硬碟里。資料庫里只存儲文件名。

存儲文件名,然後使用的時候在視圖函數里通過Flask-Uploads提供的url()方法獲取URL,或是用Flask提供的send_from_directory()方法獲取(參考這個系列第一篇文章)。

更正:出於文件管理的需要,不應該直接存儲URL。

相關鏈接

  • Flask-WTF項目地址:github.com/lepture/flas
  • Flask-WTF文件上傳:flask-wtf.readthedocs.io
  • Flask-WTF文件上傳欄位及驗證函數:flask-wtf.readthedocs.io
  • Demo Gist地址:gist.github.com/greyli/

- - - - -

更多關於Flask和Web開發的原創內容,歡迎關注知乎專欄 - Hello, Flask!。


推薦閱讀:

文件上傳漏洞分析
Flask文件上傳(五):拖拽上傳和進度條
木馬文件上傳防禦策略及幾種繞過檢測方式

TAG:Flask | Python | 文件上传 |