Flask学习4:文件上传与邮件发送

文件上传与邮件发送

原生上传文件

1.添加一个模板文件html

<!DOCTYPE html>
<html>
<head>
    <meta>
    <title>文件上传</title>
</head>
<body>
    {% if img_url %}
        <img src="{{ img_url }}">
    {% endif %}
    <form>
        <input>
        <input>
    </form>
</body>
</html>

2.添加视图函数

@app.route('/upload/', methods=['GET', 'POST'])
def upload():
    img_url = None
    if request.method == 'POST':
        photo = request.files.get('photo')
        if photo and allowed_file(photo.filename):
            # 获取文件后缀
            suffix = os.path.splitext(photo.filename)[-1]

            # 随机生成文件名
            photoname = random_string() + suffix
            # 保存上传的文件
            photo.save(os.path.join(app.config['UPLOAD_FOLDER'], photoname))

            img_url = url_for('uploaded', filename=photoname)
    return render_template('upload.html', img_url = img_url)

3.相关配置及函数

# 允许上传的文件后缀
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])

# 配置上传文件的保存位置
app.config['UPLOAD_FOLDER'] = os.getcwd()

# 限制上传文件大小
app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 8

# 判断是否是允许的文件后缀
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

# 获取上传文件的url
@app.route('/uploaded/<filename>')
def uploaded(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename)

# 生成随机字符串
def random_string(length = 32):
    import random
    base_str = 'abcdefghijklmnopqrstuvwxyz1234567890'
    return ''.join([random.choice(base_str) for i in range(length)])

4.注意事项,文件上传失败时,应从哪些方面着手

1.表单的提交方法必须是POST
2.表单的enctype属性必须设置(multipart/form-data)
3.上传的字段类型必须为file, 并且必须有name属性
4.是否超过了允许的最大尺寸
5.文件的保存位置是否还有空间,是否有权限

5.生成缩略图(需要安装Pillow库)

# 保存上传的文件
photo.save(pathname)

# 生成缩略图
# 1.打开文件
img = Image.open(pathname)
# 2.重新设置尺寸
img.thumbnail((128, 128))  # 参数为元组,指定宽高
# 3.保存修改
img.save(pathname)

扩展

环境变量:好处是可以避免隐私信息公布于众(设置时注意等号两边不要加空格)。

windows配置

设置:set NAME=dandan
获取:set NAME

linux配置

导出:export NAME=dandan
获取:echo $NAME

代码获取

@app.route('/env/')
def env():
   return os.environ.get('NAME', 'Ahh')

flask-uploads

1.说明

​在文件上传时,提供了很大的方便,比如文件类型的过滤、校验等

2.安装

pip install flask-upload

3.使用

from flask_uploads import UploadSet, IMAGES, configure_uploads, patch_request_class


# 上传文件的大小

app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 8

# 上传文件的保存位置

import os
app.config['UPLOADED_PHOTOS_DEST'] = os.getcwd()


# 创建上传对象, 需要指定过滤的文件后缀

photos = UploadSet('photos', IMAGES)
configure_uploads(app, photos)


# 配置上传文件大小, 默认64M,设置为None时使用MAX_CONTENT_LENGTH的大小

patch_request_class(app, size=None)


@app.route('/upload/', methods=['GET', 'POST'])
def upload():
   img_url = None
   if request.method == 'POST' and 'photo' in request.files:
       # 保存文件
       filename = photos.save(request.files['photo'])

       # 获取保存文件的url
       img_url = photos.url(filename)
   return render_template('upload.html', img_url = img_url)





# html

<!DOCTYPE html>
<html>
<head>
   <meta>
   <title>文件上传</title>
</head>
<body>
   {% if img_url %}
       <img src="{{ img_url }}">
   {% endif %}
   <form>
       <input>
       <input>
   </form>
</body>
</html>

完整的文件上传

1.flask-uploads配置同上

2.flask-wtf配置

# 导入表单基类

from flask_wtf import FlaskForm

# 导入文件上传字段及验证器

from flask_wtf.file import FileField, FileRequired, FileAllowed
from wtforms import SubmitField


# 上传文件表单类

class UploadForm(FlaskForm):
   photo = FileField('头像上传', validators=[FileRequired('文件未选择'), FileAllowed(photos,)])
   submit = SubmitField('上传')

3.视图函数

# 随机生成文件名

def random_string(length = 32):
   import random
   base_str = '1234567890qwertyuiopasdfghjklmnbvcxz'
   return ''.join([random.choice(base_str) for i in range(length)])

@app.route('/upload/', methods=['GET', 'POST'])
def upload():
   img_url = None
   form = UploadForm()
   if form.validate_on_submit():
       # 获取文件后缀
       suffix = os.path.splitext(form.photo.data.filename)[1]
       filename = random_string() + suffix

       # 保存上传文件
       photos.save(form.photo.data, name=filename)

       # 生成缩略图
       pathname = os.path.join(app.config['UPLOADED_PHOTOS_DEST'], filename)
       # 打开文件
       img = Image.open(pathname)

       # 设置尺寸
       img.thumbnail((128, 128))

       img.save(pathname)

       img_url = photos.url(filename)
   return render_template('upload2.html', form=form, img_url=img_url)

4.模板文件

{% extends 'bootstrap/base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}

{% block content %}
   <div>
       {% if img_url %}
           <img src="{{ img_url }}">
       {% endif %}

       {{ wtf.quick_form(form) }}
   </div>
{% endblock %}

flask-mail

1.说明

​是一个邮件发送的扩展库,使用非常方便

2.安装

pip install flask-mail

3.配置

from flask_mail import Mail, Message


# 配置一定要写在创建Mail对象之前,否则不起作用


# 邮箱服务器

import os
app.config['MAIL_SERVER'] = os.environ.get('MAIL_SERVER', 'smtp.163.com')

# 用户名

app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME', 'xxx@163.com')

# 密码,密码有时是授权码

app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD', 'xxxxxx')


# 创建对象

mail = Mail(app)

4.发送邮件

@app.route('/')
def hello_world():
   # 创建邮件对象
   msg = Message(subject='丹丹的测试邮件', recipients=['xxx@qq.com'], sender=app.config['MAIL_USERNAME'])
   # 浏览器打开显示这个
   msg.html = '<h1>Nice day</h1>'
   # 终端打开显示这个
   msg.body = 'Body'
   mail.send(msg)
   return '邮件已发送!'

5.封装函数,发送邮件

# 封装函数,发送邮件

def send_mail(to, subject, template, **kwargs):
   # 创建邮件对象
   msg = Message(subject=subject, recipients=to, sender=app.config['MAIL_USERNAME'])
   # 浏览器打开显示这个
   msg.html = '<b>Nice day</b>'
   # 终端打开显示这个
   msg.body = 'Nice day'
   mail.send(msg)

6.异步发送邮件

# 异步发送邮件

def async_send_mail(app, msg):
   # 发送邮件需要程序上下文,新的线程中没有上下文,需要手动创建
   with app.app_context():
       # 发送邮件
       mail.send(msg)



# 封装函数,发送邮件

def send_mail(to, subject, template, **kwargs):
   # 根据current_app获取当前实例
   app = current_app._get_current_object()
   # 创建邮件对象
   msg = Message(subject=subject, recipients=to, sender=app.config['MAIL_USERNAME'])
   # 浏览器打开显示这个
   msg.html = render_template(template + '.html', **kwargs)
   # 终端打开显示这个
   msg.body = render_template(template + '.txt', **kwargs)
   # mail.send(msg)

   # 创建线程
   thr = Thread(target=async_send_mail, args=[current_app, msg])
   # 启动线程
   thr.start()
   return thr
标签:Flask 发布于:2019-10-21 13:10:44