第十阶段 -- Flask框架05:【Flask高级05:上传、访问文件】

1. 上传、访问文件

  1. 上传文件的步骤
    1. 在模版html中,表单需要指定encotype='multipart/form-data'才能上传文件。
    2. 在后台如果想要获取上传的文件,那么应该使用request.files.get('文件名')来获取。
    3. 保存文件之前,先要使用werkzeug.utils.secure_filename来对上传上来的文件名进行一个过滤。能保证不会有安全问题。
    4. 获取到上传上来的文件后,使用文件对象.save(路径)方法来保存文件。路径=完整路径=路径名+文件名
  • 【upload.html页面】
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件</title>
</head>
<body>
   <form action="" method="post" enctype="multipart/form-data">
    <table>
            <tr>
                <td>头像:</td>
                <td><input type="file" name="pichead"></td>
            </tr>
            <tr>
                <td>描述:</td>
                <td><input type="text" name="desc"></td>
            </tr>
            <tr>
                <td></td>
                <td><input type="submit" value="提交"></td>
            </tr>
    </table>
</form>
</body>
</html>

  • 【app.py文件】
from flask import Flask,request,render_template
import os
from werkzeug.utils import secure_filename

app = Flask(__name__)
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:
        desc = request.form.get("desc")
        pichead = request.files.get("pichead")
        filename = secure_filename(pichead.filename) #包装一下 保证文件安全
        # pichead.save(os.path.join(UPLOAD_PATH,pichead.filename)) #可优化
        pichead.save(os.path.join(UPLOAD_PATH,filename)) #已优化
        print(desc)
        return '文件上传成功'

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

  1. 访问文件:从服务器上读取文件,应该定义一个url与视图函数,来获取指定的文件。在这个视图函数中,使用send_from_directory(文件的目录,文件名)来获取。
from flask import Flask
import os
from flask import send_from_directory

app = Flask(__name__)
UPLOAD_PATH = os.path.join(os.path.dirname(__file__),'images')

@app.route('/images/<filename>/')
def get_image(filename):
    return send_from_directory(UPLOAD_PATH,filename)

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

2. 利用flask_wtf验证上传的文件

  • 关键点:
  1. 定义验证表单类的时候,对文件类型的字段,需要采用FileField这个类型,即wtforms.FileField。

  2. 验证器需要从flask_wtf.file中导入。flask_wtf.file.FileRequiredflask_wtf.file.FileAllowed

  3. flask_wtf.file.FileRequired是用来验证文件上传不能为空。

  4. flask_wtf.file.FileAllowed用来验证上传的文件的后缀名, 如常见图片后缀 .jpg 和.png以及.gif等。

  5. 在视图函数中,需要使用from werkzeug.datastructures import CombinedMultiDict来把request.formrequest.files来进行合并。

  6. 最后使用 表单验证对象.validate()进行验证。

  • 代码如下

    【upload.html页面】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件</title>
</head>
<body>
   <form action="" method="post" enctype="multipart/form-data">
    <table>
            <tr>
                <td>头像:</td>
                <td><input type="file" name="pichead"></td>
            </tr>
            <tr>
                <td>描述:</td>
                <td><input type="text" name="desc"></td>
            </tr>
            <tr>
                <td></td>
                <td><input type="submit" value="提交"></td>
            </tr>
    </table>
</form>
</body>
</html>

​ 【formscheck.py文件】

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

class UploadForm(Form):
    pichead = FileField(validators=[FileRequired(),FileAllowed(['jpg','png','gif'])])
    desc = StringField(validators=[InputRequired()])

​ 【app.py文件】

from flask import Flask,request,render_template
import os
from werkzeug.utils import secure_filename
from formscheck import UploadForm
from werkzeug.datastructures import  CombinedMultiDict

app = Flask(__name__)
UPLOAD_PATH = os.path.join(os.path.dirname(__file__),'images')

 #利用flask-wtf验证上传的文件
@app.route('/upload/',methods=['GET','POST'])
def upload():
    if request.method == 'GET':
        return render_template('upload.html')
    else:
        form = UploadForm(CombinedMultiDict([request.form,request.files]))
        if form.validate():
            # desc = request.form.get("desc")
            # pichead = request.files.get("pichead")
            desc = form.desc.data
            pichead = form.pichead.data
            filename = secure_filename(pichead.filename)
            pichead.save(os.path.join(UPLOAD_PATH,filename))
            print(desc)
            return '文件上传成功'
        else:
            print(form.errors)
            return "文件上传失败"

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

3. 示例

【33_wtforms_demo.py】

from flask import Flask,request,render_template,session,send_from_directory
from formscheck import RegisterForm,RegisterForm2,CreateForm,UploadForm
from werkzeug.utils import secure_filename
from werkzeug.datastructures import CombinedMultiDict
import os
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)

UPLOAD_PATH=os.path.join(os.path.dirname(__file__),"images")  # D:\python_project\33_wtforms_demo\images

@app.route('/')
def hello_world():
    return 'Hello World!'

# wtforms表单验证的基本使用
@app.route('/register/',methods=['GET','POST'])
def register():
    if request.method == 'GET':
        return render_template('register.html')
    else:
        # 使用表单验证对象进行验证
        form = RegisterForm(request.form)
        if form.validate(): # 验证;要么ok;要么no
            return "验证通过"
        else:
            print(form.errors)
            return "数据验证通不过"

import random
# wtforms常用验证器使用
@app.route('/register2/',methods=['GET','POST'])
def login():
    if request.method == 'GET':
        # 自定义验证器     实现验证码验证
        code = random.randint(1000,9999)  # 生成一个随机4位整数值的验证码
        session['code'] = str(code)
        return render_template("register2.html")
    else:
        form = RegisterForm2(request.form)
        if form.validate():
            return "验证OK"
        else:
            print(form.errors)
            return "验证失败"

import uuid
print(uuid.uuid4())#edbfa1d6-28f2-4f40-9111-528141a8e77d

# WTForms渲染模版  了解
@app.route('/createform/')
def createform():
        form = CreateForm()
        return render_template('create_form.html',form=form)

		################ 上传、访问文件 ################    

# flask 上传文件的实现
# @app.route('/upload/',methods=['GET','POST'])
# def upload():
#     if request.method == 'GET':
#         return render_template('upload.html')
#     else:
#         desc = request.form.get("desc")
#         pichead = request.files.get("pichead")
#         print(desc)
#         #保存到服务器 #D:\python_project\33_wtforms_demo\images
#         filename = secure_filename(pichead.filename) #对pichead.filename文件做一下 包装   保证文件名更安全
#         # pichead.save(os.path.join(UPLOAD_PATH,pichead.filename)) #文件名处可优化
#         pichead.save(os.path.join(UPLOAD_PATH,filename)) #已优化
#         return '文件上传成功'

# 访问服务器上(已经上传成功)的图片
@app.route('/images/<filename>/')
def get_image(filename):
    return send_from_directory(UPLOAD_PATH,filename)

# 利用flask-wtf验证上传的文件
@app.route('/upload/',methods=['GET','POST'])
def upload():
    if request.method == 'GET':
        return render_template('upload.html')
    else:
        form = UploadForm(CombinedMultiDict([request.form,request.files]))
        if form.validate():
            # desc = request.form.get("desc")
            # print(type(request.form))
            # pichead = request.files.get("pichead")
            # 从form对象里边获取 desc  和pichead数据
            pichead =form.pichead.data
            print(pichead.filename)  # 获取上传的文件名
            print(form.desc.data)
            # print(desc)
            # 保存到服务器 #D:\python_project\33_wtforms_demo\images
            filename = secure_filename(pichead.filename)  # 对pichead.filename文件做一下 包装   保证文件名更安全
            # pichead.save(os.path.join(UPLOAD_PATH,pichead.filename)) #文件名处可优化
            pichead.save(os.path.join(UPLOAD_PATH, filename))  # 已优化
            return '文件上传成功'
        else:
            print(form.errors)
            return "上传文件失败"  # 不符合图片格式要求

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

formscheck.py

# 工具类
from wtforms import Form,StringField,IntegerField,RadioField,BooleanField,SelectField,TextAreaField,DateField,FileField
from wtforms.validators import  Length,EqualTo,Email,InputRequired,NumberRange,Regexp,URL,UUID,ValidationError
from flask import session

# 利用flask-wtf 验证上传的文件
from  flask_wtf.file import  FileRequired,FileAllowed

# 定义一个表单验证类
class RegisterForm(Form):
    uname = StringField( validators=[Length(min=2,max=15,message="用户名的长度必须是2-15之间")])
    pwd = StringField(validators=[Length(min=6, max=12)])
    pwd2 = StringField(validators=[Length(min=6,max=12),EqualTo("pwd",message="两次输入密码不一致")])

# 定义一个表单验证类2
class RegisterForm2(Form):
    email = StringField(validators=[Email()])
    uname = StringField(validators=[InputRequired()])
    age = IntegerField(validators=[NumberRange(min=18,max=40)])
    phone = StringField(validators=[Regexp(r'1[34578]\d{9}')])
    phomepage = StringField(validators=[URL()])
    uuid = StringField(validators=[UUID()])
    code = StringField(validators=[Length(min=4,max=4)])
    # 光有长度验证  不能满足验证码验证需求,此时需要自定义验证器来对 某字段验证进行强化
    def validate_code(self,field):
        # 去字段field对象上的值来做验证
        print(field.data,session.get('code'))
        scode = session.get('code')
        if field.data != scode:
            raise  ValidationError(message='输入的验证码不一致!!')

# wtforms 渲染模版的定义
class CreateForm(Form):
    # uname = StringField(validators = [InputRequired()])
    uname = StringField("用户名:",validators = [InputRequired()])
    age = IntegerField("年龄:",validators = [NumberRange(18,40)])
    remember = BooleanField("记住我:")
    addr = SelectField('地址:',choices=[('bj',"北京"),('sj','上海'),('tj','天津')])

    		################ 上传、访问文件 ################

# 验证上传的文件类型
class  UploadForm(Form):
    pichead = FileField(validators=[FileRequired(),FileAllowed(["jpg","png","gif"])])
    desc = StringField(validators=[InputRequired()])

【upload.html】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件</title>
</head>
<body>
   <form action="" method="post" enctype="multipart/form-data">
    <table>
            <tr>
                <td>头像:</td>
                <td><input type="file" name="pichead"></td>
            </tr>
            <tr>
                <td>描述:</td>
                <td><input type="text" name="desc"></td>
            </tr>
            <tr>
                <td></td>
                <td><input type="submit" value="提交"></td>
            </tr>
    </table>
</form>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值