Flask筆記:文件上傳


文件上傳

  • enctype:在HTML中的form表單中form標簽默認是`enctype="application/x-www-form-urlencoded"`,在文件上傳時需要設置為`enctype="multipart/form-data"`,不然文件上傳不會成功。
  • 后台獲取上傳的文件:fileobj = request.files.get('input_file_name'),需要注意的是,get方法的參數是HTML中文件input標簽指定的name屬性值,而不是上傳的文件名稱。
  • 文件名處理:使用fileobj.filename即可獲取到文件名,但是不建議直接使用這個文件名,為了安全考慮,建議使用from werkzeug.utils import secure_filename對文件名進行過濾處理一下。
  • 保存文件:使用返回的文件對象的save方法即可,fileobj.save(file_path),file_path是保存文件的絕對路徑。
  • 后台發送文件到瀏覽器:使用from flask import send_from_directory,直接返回對應的文件即可,send_from_directory需要兩個參數,第一個參數是文件所在目錄,第二個參數是文件名。

 

文件驗證

  • Form驗證:是使用from wtforms import Form的子類進行驗證。
  • 字段類型:from wtforms import FileField,FileField表示文件類型。
  • 驗證器:from flask_wtf.file import FileRequired, FileAllowed,FileRequired表示文件不能為空,FileAllowed表示文件的后綴名類型。
  • 多元素結合:request中有文件和文本等多種類型的元素時,從request中獲取數據的方式也不同時,比如:request.form和request.files,再想要使用Form表單對象進行驗證時,就需要使用from werkzeug.datastructures import CombinedMultiDict將多種元素結合起來,再傳入表單對象進行驗證。
  • 數據獲取:經過表單對象驗證過后,可以通過“form.[attr_name].data”的方式獲取文件和文本等數據,這種方式和通過request獲取數據是一樣的。

 

簡單示例:

HTML文件upload.html主要代碼

 <form action="" method="post" enctype="multipart/form-data">
        <table>
            <tbody>
                <tr>
                    <td>頭像:</td>
                    <td><input type="file" name="avatar"></td>
                </tr>
                <tr>
                    <td>描述:</td>
                    <td><input type="text" name="desc"></td>
                </tr>
                <tr>
                    <td></td>
                    <td><input type="submit" value="提交"></td>
                </tr>
            </tbody>
        </table>
    </form>

瀏覽器效果

表單對象文件forms.py

from wtforms import Form, FileField, StringField
from wtforms.validators import InputRequired
from flask_wtf.file import FileRequired, FileAllowed


class UploadFileForm(Form):
    # FileField表示字段為文件類型
    avatar = FileField(validators=[FileRequired(), FileAllowed(['jpg', 'png', 'gif'])])
    # StringField表示字段為字符串類型
    desc = StringField(validators=[InputRequired()])

 

 主py文件

import os
from werkzeug.utils import secure_filename
from werkzeug.datastructures import CombinedMultiDict
from flask import Flask, request, render_template, send_from_directory
from forms import UploadFileForm

app = Flask(__name__)

# 所有圖片文件放在根目錄的images文件夾下
UPLOAD_PATH = os.path.join(os.path.dirname(__file__), 'images')


@app.route('/upload/', methods=['GET', 'POST'])
def upload():
    if request.method == 'GET':
        return render_template('upload.html')
    else:
        # 結合表單request中的多種表單元素
        form = UploadFileForm(CombinedMultiDict([request.form, request.files]))
        if form.validate():
            # 根據html中對應標簽的name屬性獲取對應上傳的數據
            # request.form相當於一個字典
            # desc = request.form.get('desc')
            desc = form.desc.data
            print(desc)
            # 獲取文件需要從request.files中獲取
            # avatar = request.files.get('avatar')
            avatar = form.avatar.data
            # 為了安全起見,需要將文件名使用特殊方式(secure_filename函數)過濾處理一下
            # secure_filename對中文支持不是很好,可以對文件名進行轉換,但是仍然推薦使用這個函數來進行處理一下
            filename = secure_filename(avatar.filename)
            # 返回的文件對象可以直接通過它的save方法傳入路徑保存,路徑不能是相對路徑,需要是絕對路徑
            avatar.save(os.path.join(UPLOAD_PATH, filename))
            return '文件上傳成功!'
        else:
            print(form.errors)
            return '文件上傳失敗!'


@app.route('/images/<filename>/')
def get_image(filename):
    # 獲取文件返回到瀏覽器中,使用send_from_directory,第一個參數是文件目錄,第二個參數是文件名
    return send_from_directory(UPLOAD_PATH, filename)


if __name__ == '__main__':
    app.run(debug=True)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM