flask学习04文件上传与邮件发送

文件上传与邮件发送

原生上传文件

  1. 添加一个模板文件

     
       
       
    <html>
    <head>
        <title>原生文件上传</title>
    </head>
    <body>
        {% if img_url %}
            <img src="{{ img_url }}">
        {% endif %}
        <form method="post" enctype="multipart/form-data">
            <input type="file" name="photo" />
            <input type="submit" value="上传" />
        </form>
    </body>
    </html>
  2. 添加视图函数

     
       
       
    @app.route('/upload/', methods=['GET', 'POST'])
    def upload():
        img_url = None
        if request.method == 'POST':
            file = request.files.get('photo')
            if file and allowed_file(file.filename):
                # 获取文件后缀
                suffix = os.path.splitext(file.filename)[1]
                # 生成随机文件名
                filename = random_string() + suffix
                # 保存上传文件
                file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
                # 构造上传的文件的访问URL
                img_url = url_for('uploaded', filename=filename)
        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
    # 生成随机的字符串
    def random_string(length=32):
        import random
        base_str = 'abcdefghijklmnopqrstuvwxyz1234567890'
        return ''.join(random.choice(base_str) for i in range(length))
    # 获取上传文件
    @app.route('/uploaded/<filename>')
    def uploaded(filename):
        # 安全的发送文件
        return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
  4. 注意事项,文件上传失败时,应从哪些方面着手

     
       
       
    1.表单的提交方法必须是POST
    2.表单的enctype属性必须设置为multipart/form-data
    3.上传的字段类型必须为file,并且必须有name属性
    4.是否超过运行的最大尺寸
    5.文件的保存位置是否有空间,是否有权限
  5. 生成缩略图,需要安装pillow库

     
       
       
    # 导入图片处理的类,默认PIL不支持python.x,安装pillow后就可以了
    from PIL import Image
    # 生成缩略图
    # 1.打开文件
    img = Image.open(pathname)
    # 2.重设尺寸
    img.thumbnail((128, 128))
    # 3.保存修改
    img.save(pathname)

flask-uploads

  1. 说明:在文件上传时,提供了很大的方便,如:文件类型的过滤,校验等

  2. 安装:pip install flask-uploads

  3. 使用:

    相关配置:

     
       
       
    # 上传文件的大小
    app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 8
    # 上传文件的保存位置
    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)

    模板文件:同原生的文件上传upload.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, message='只能上传图片文件')])
        submit = SubmitField('上传')
  3. 视图函数:

     
       
       
    @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)
            # 获取上传文件的url
            img_url = photos.url(filename)
        return render_template('upload.html', form=form, img_url=img_url)
  4. 模板文件upload.html

     
       
       
    {% extends 'bootstrap/base.html' %}
    {% import 'bootstrap/wtf.html' as wtf %}
    {% block content %}
        <div class="container">
            {% if img_url %}
                <img src="{{ img_url }}" />
            {% endif %}
            {{ wtf.quick_form(form) }}
        </div>
    {% endblock %}

flask-mail

  1. 说明:是一个邮件发送的扩展库,使用非常方便

  2. 安装:pip install flask-mail

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

     
       
       
    # 导入类库
    from flask_mail import Mail, Message
    # 邮箱服务器
    app.config['MAIL_SERVER'] = os.environ.get('MAIL_SERVER', 'smtp.1000phone.com')
    # 用户名
    app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME', 'lijie@1000phone.com')
    # 密码,密码有时是授权码
    app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD', '123456')
    # 创建对象
    mail = Mail(app)
  4. 发送邮件

     
       
       
    @app.route('/')
    def index():
        # 创建邮件对象
        msg = Message(subject='账户激活', recipients=['51598885@qq.com'], 
                      sender=app.config['MAIL_USERNAME'])
        # 浏览器打开邮件显示内容
        msg.html = '<h1>你好,Mr cheng,激活请点击右边链接</h1>'
        # 终端接受邮件显示内容
        msg.body = '你好,Mr cheng,激活请点击右边链接'
        
        # 发送邮件
        mail.send(message=msg)
        return '邮件已发送'
  5. 封装函数,发送邮件

     
       
       
    # 封装函数,发送邮件
    def send_mail(to, subject, template, **kwargs):
        # 创建邮件对象
        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(message=msg)

    调用邮件发送函数:

     
       
       
    @app.route('/')
    def index():
        send_mail('51598885@qq.com', '找回密码', 'activate', 
                  username='陈承念')
        return '邮件已发送'
  6. 异步发送邮件

     
       
       
    # 异步发送邮件
    def async_send_mail(app, msg):
        # 发送邮件需要程序上下文,新的线程没有上下文,需要手动创建
        with app.app_context():
            # 发送邮件
            mail.send(message=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)
        # 创建线程
        thr = Thread(target=async_send_mail, args=[app, msg])
        # 启动线程
        thr.start()
        return thr

扩展

环境变量:好处是可以避免隐私的信息公布于众

  1. windows配置

     
       
       
    设置:set NAME=xiaoming
    获取:set NAME
  2. linux配置

     
       
       
    导出:export NAME=xiaoming
    获取:echo $NAME
  3. 代码获取

     
       
       
    import os
    app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY') or '123456'
    os.environ.get('NAME', 'default')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值