flask-文件上传与邮件发送

版权声明:转载请注明,否则将追究相关法律责任 https://blog.csdn.net/zangshuge/article/details/82024157

文件上传与邮件发送

原生上传

  • 模板文件

    <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__)
    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等实现文件上传
  • 使用:
    • 各种配置及对象创建
    • 注意对象创建的先后顺序
    • 上传文件的校验处理过程与上面一样
  • 说明:代码见项目《03-full-upload》

flask-mail

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

  • 安装:pip install flask-mail

  • 使用:

    from flask_mail import Mail, Message
    import os
    
    
    # 邮件配置,一定要放在对象创建之前
    
    
    # 邮箱服务器
    
    app.config['MAIL_SERVER'] = 'smtp.1000phone.com'
    
    # 用户名
    
    app.config['MAIL_USERNAME'] = '[email protected]'
    
    # 密码
    
    app.config['MAIL_PASSWORD'] = os.getenv('MAIL_PASSWORD', '123456')
    
    
    # 创建发送邮件的对象
    
    mail = Mail(app)
    
    @app.route('/send/')
    def send():
      # 创建邮件消息对象
      msg = Message('账户激活',
                    recipients=['[email protected]'],
                    sender=app.config['MAIL_USERNAME'])
      # 设置邮件内容
      msg.html = '恭喜你,中奖了!'
      # 发送邮件
      mail.send(msg)
      return '邮件发送成功'
  • 总结:

    扫描二维码关注公众号,回复: 2905955 查看本文章
    • 书写邮箱相关配置
    • 创建发送邮件的(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('账户激活', '[email protected]', '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_USR_SSL'] = True
    

猜你喜欢

转载自blog.csdn.net/zangshuge/article/details/82024157
今日推荐