zoukankan      html  css  js  c++  java
  • Flask—04-文件上传与邮件发送(自带优化)

    文件上传与邮件发送

    • 可以按照标题分别直接粘贴对应的文件夹,运行直接用:

      原生上传

    • 模板文件

      <form method="post" enctype="multipart/form-data">
          <input type="file" name="photo" /><br />
          <input type="submit" value="上传" />
      </form>
      
    • 视图函数

      @app.route('/upload/', methods=['GET', 'POST'])
      def upload():
          if request.method == 'POST':
              # 获取上传对象
              photo = request.files.get('photo')
              if photo:
                  # 保存上传文件,参数是文件保存的路径名
                  photo.save(photo.filename)
                  return '文件上传成功'
              return '文件上传失败'
          return render_template('upload.html')
      
    • 优化完善

      import os
      from flask import send_from_directory
      
      # 上传文件保存位置
      app.config['UPLOADED_FOLDER'] = os.path.join(os.getcwd(), 'static/upload')
      # 请求大小(文件大小限制)
      app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 8
      
      # 判断是否是允许的文件类型
      def allowed_file(filename):
          return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_SUFFIX
      
      # 展示上传的文件
      @app.route('/uploaded/<filename>')
      def upladed(filename):
          # 安全的发送文件
          return send_from_directory(app.config['UPLOADED_FOLDER'], filename)
      
      @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):
                  # 拼接文件保存的完整路径名
                  pathname = os.path.join(app.config['UPLOADED_FOLDER'],
                                          photo.filename)
                  # 保存上传文件,参数是文件保存的路径名
                  photo.save(pathname)
                  img_url = url_for('upladed', filename=photo.filename)
          return render_template('upload.html', img_url=img_url)
      

      优化:大小限定、类型限定、保存位置、查看上传文件

    flask-uploads

    • 说明:极大地优化了文件上传的操作,使用非常方便

    • 安装:pip install flask-uploads

    • 使用:

      • 配置
      from flask_uploads import UploadSet, IMAGES
      from flask_uploads import configure_uploads
      from flask_uploads import patch_request_class
      import os
      
      app = Flask(__name__)
      # 设置文件的大小:8M=8*1024*1024k
      app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 8
      app.config['UPLOADED_PHOTOS_DEST'] = os.path.join(os.getcwd(), 'static/upload')
      # 创建上传对象,指定名字和上传文件的类型
      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':
              # 获取上传对象
              photo = request.files.get('photo')
              if photo:
                  # 保存上传文件
                  photos.save(photo)
                  # 获取上传文件的地址
                  img_url = photos.url(photo.filename)
          return render_template('upload.html', img_url=img_url)
      
      • 优化上传:生成随机文件名,生成缩略图(PIL模块,只支持py2,py3中使用需要安装pillow)
      # 生成随机字符串
      def random_string(length=32):
          import random
          base_str = 'abcdefghijklmnopqrstuvwxyz1234567890'
          return ''.join(random.choice(base_str) for i in range(length))
      
      @app.route('/upload/', methods=['GET', 'POST'])
      def upload():
          img_url = None
          if request.method == 'POST':
              # 获取上传对象
              photo = request.files.get('photo')
              if photo:
                  # 提取文件后缀
                  suffix = os.path.splitext(photo.filename)[1]
                  # 生成随机文件名
                  filename = random_string() + suffix
                  # 保存上传文件
                  photos.save(photo, name=filename)
                  # 生成缩略图
                  from PIL import Image
                  # 拼接完整路径名
                  pathname = os.path.join(app.config['UPLOADED_PHOTOS_DEST'], filename)
                  # 打开文件
                  img = Image.open(pathname)
                  # 设置大小
                  img.thumbnail((64, 64))
                  # 保存修改后的图片
                  img.save(pathname)
                  # 获取上传文件的地址
                  img_url = photos.url(filename)
          return render_template('upload.html', img_url=img_url)
      

    综合使用

    • 要求:结合flask-bootstrap、flask-wtf、flask-uploads等实现文件上传
    • 使用:
      • 各种配置及对象创建
      • 注意对象创建的先后顺序
      • 上传文件的校验处理过程与上面一样

    flask-mail

    • 说明:专门用来实现邮件发送的扩展库,使用非常方便。

    • 安装:pip install flask-mail

    • 使用:

      from flask_mail import Mail, Message
      import os
      
      # 邮件配置,一定要放在对象创建之前
      # 邮箱服务器:不同类型邮箱服务器不同,不知道的请百度
      app.config['MAIL_SERVER'] = 'smtp.xxx.com'
      # 用户名
      app.config['MAIL_USERNAME'] = 'xxx@xxx.com'
      # 密码:如果密码添加到了环境变量可以直接引用'MAIL_PASSWORD',否则直接把'123456'换成自己的邮箱密码。
      app.config['MAIL_PASSWORD'] = os.getenv('MAIL_PASSWORD', '123456')
      
      # 创建发送邮件的对象
      mail = Mail(app)
      
      @app.route('/send/')
      def send():
          # 创建邮件消息对象
          msg = Message('账户激活',
                        recipients=['xxx@qq.com'],
                        sender=app.config['MAIL_USERNAME'])
          # 设置邮件内容
          msg.html = '恭喜你,中奖了!'
          # 发送邮件
          mail.send(msg)
          return '邮件发送成功'
      
    • 总结:

      • 书写邮箱相关配置
      • 创建发送邮件的(Mail)对象
      • 创建邮件消息(Message)对象
      • 使用mail的send方法发送邮件
    • 封装函数发送邮件

      # 封装函数发送邮件
      def send_mail(subject, to, template, **kwargs):
          # 处理邮件接收者
          if isinstance(to, list):
              recipients = to
          elif isinstance(to, str):
              recipients = to.split(',')
          else:
              raise Exception('邮件接收者参数有误')
          # 创建邮件消息对象
          msg = Message(subject=subject, recipients=recipients,
                        sender=app.config['MAIL_USERNAME'])
          # 设置邮件内容
          msg.html = render_template(template, **kwargs)
          # 发送邮件
          mail.send(msg)
      
      @app.route('/send/')
      def send():
          # 调用函数即可发送邮件
          send_mail('账户激活', 'xxx@qq.com', 'activate.html', name='八戒')
          return '邮件发送成功'
      
    • 异步发送邮件

      from flask import current_app
      from threading import Thread
      
      # 异步发送邮件
      def async_send_mail(app, msg):
          # 邮件发送必须在程序上下文中进行
          # 新的线程没有上下文,因此需要手动创建上下文
          with app.app_context():
              mail.send(msg)   
      
      # 封装函数发送邮件
      def send_mail(subject, to, template, **kwargs):
            # 处理邮件接收者
          if isinstance(to, list):
              recipients = to
          elif isinstance(to, str):
              recipients = to.split(',')
          else:
              raise Exception('邮件接收者参数有误')
          # 从代理中获取原始对象
          app = current_app._get_current_object()
          # 创建邮件消息对象
          msg = Message(subject=subject,recipients=recipients,sender=app.config['MAIL_USERNAME'])
          # 设置邮件内容
          msg.html = render_template(template, **kwargs)
          # 发送邮件:同步发送,会阻塞运行
          # mail.send(msg)
          # 创建一个线程,在新的线程中发送邮件
          thr = Thread(target=async_send_mail, args=(app, msg))
          # 启动线程
          thr.start()
          # 返回线程
          return thr
      
    • QQ邮箱发送配置

      # 密码,QQ邮箱需要使用授权码
      app.config['MAIL_PASSWORD'] = os.getenv('MAIL_PASSWORD', '123456')
      # QQ邮箱配置
      # app.config['MAIL_PORT'] = 465
      # 加密传输
      # app.config['MAIL_USE_SSL'] = True
      
  • 相关阅读:
    rn相关文档
    《浅谈我眼中的express、koa和koa2》好文留存+笔记
    (四)Spring 对DAO 的支持
    (三)Spring 之AOP 详解
    (二)Spring 之IOC 详解
    SVN文件上感叹号、加号、问号等图标的原因
    Windows平台下不同版本SVN对比
    eclipse中启动Genymotion模拟器的错误
    (一)问候Spring4
    (十一)Hibernate 高级配置
  • 原文地址:https://www.cnblogs.com/swjblog/p/9726896.html
Copyright © 2011-2022 走看看