码迷,mamicode.com
首页 > Web开发 > 详细

文件上传与邮件发送

时间:2019-01-04 19:40:52      阅读:289      评论:0      收藏:0      [点我收藏+]

标签:png   imp   smtp   函数   邮件   ade   rms   获取   contain   

# 文件上传与邮件发送

### 原生实现

- 模板文件

  ```html
  <form method="post" enctype="multipart/form-data">
      <input type="file" name="photo" /><br />
      <input type="submit" value="上传" />
  </form>
  ```

- 视图函数

  ```python
  import os

  # 配置上传文件保存目录
  app.config[UPLOADED_FOLDER] = os.path.join(os.getcwd(), static/upload)

  @app.route(/upload/, methods=[GET, POST])
  def upload():
      if request.method == POST:
          # 获取上传对象
          photo = request.files.get(photo)
          if photo:
              # 拼接保存路径名
              pathname = os.path.join(app.config[UPLOADED_FOLDER], photo.filename)
              # 保存上传文件
              photo.save(pathname)
              return 上传成功
          else:
              return 上传失败
      return render_template(upload.html)
  ```

- 上传限制设置

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

  # 判断是否是允许的后缀
  def allowed_file(filename):
      return . in filename and filename.rsplit(., 1)[1] in ALLOWED_SUFFIX
      
  # 限制请求大小
  app.config[MAX_CONTENT_LENGTH] = 1024 * 1024 * 8

  # 展示上传的图片
  @app.route(/uploaded/<filename>)
  def uploaded(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)
              # 构造上传文件的url
              img_url = url_for(uploaded, filename=photo.filename)
      return render_template(upload.html, img_url=img_url)
  ```

### flask-uploads

- 说明:极大的的简化了文件上传相关的操作,使用非常方面。

- 安装:`pip install flask-uploads`

- 使用:

  - 配置

  ```python
  from flask_uploads import UploadSet, IMAGES
  from flask_uploads import configure_uploads
  from flask_uploads import patch_request_class
  import os

  app.config[UPLOADED_PHOTOS_DEST] = os.getcwd()
  app.config[MAX_CONTENT_LENGTH] = 8 * 1024 * 1024
  # 创建上传对象
  photos = UploadSet(photos, IMAGES)
  # 配置上传对象
  configure_uploads(app, photos)
  # 配置上传文件大小,默认为64M,
  # 若设置为None,则以MAX_CONTENT_LENGTH配置为准
  patch_request_class(app, size=None)
  ```

  - 视图函数

  ```python
  @app.route(/upload/, methods=[GET, POST])
  def upload():
      img_url = None
      if request.method == POST:
          # 获取上传对象
          photo = request.files.get(photo)
          if photo:
              # 保存上传文件,返回文件名
              filename = photos.save(photo)
              # 根据文件名获取上传文件的URL
              img_url = photos.url(filename)
      return render_template(upload.html, img_url=img_url)
  ```

### 综合使用

- 要求:结合flask-bootstrap、flask-wtf、flask-uploads等完成文件上传

- 使用:

  - 配置

  ```python
  from flask_wtf import FlaskForm
  from flask_wtf.file import FileField, FileAllowed, FileRequired
  from wtforms import SubmitField
  from flask_uploads import UploadSet, IMAGES
  from flask_uploads import configure_uploads
  from flask_uploads import patch_request_class
  from flask_bootstrap import Bootstrap
  import os

  bootstrap = Bootstrap(app)

  app.config[SECRET_KEY] = 123456
  app.config[MAX_CONTENT_LENGTH] = 8 * 1024 * 1024
  app.config[UPLOADED_PHOTOS_DEST] = os.path.join(os.getcwd(), static/upload)

  photos = UploadSet(photos, IMAGES)
  configure_uploads(app, photos)
  patch_request_class(app, size=None)

  class UploadForm(FlaskForm):
      photo = FileField(头像, validators=[FileRequired(message=请选择文件), 
                                          FileAllowed(photos, message=只能上传图片文件)])
      submit = SubmitField(上传)
  ```

  - 视图函数

  ```python
  @app.route(/upload/, methods=[GET, POST])
  def upload():
      img_url = None
      form = UploadForm()
      if form.validate_on_submit():
          photo = form.photo.data
          filename = photos.save(photo)
          img_url = photos.url(filename)
      return render_template(upload.html, form=form, img_url=img_url)
  ```

  - 模板文件

  ```html
  {% extends bootstrap/base.html %}

  {% from bootstrap/wtf.html import quick_form %}

  {% block title %}完整的文件上传{% endblock %}

  {% block content %}
      <div class="container">
          {% if img_url %}
              <img src="{{ img_url }}">
          {% endif %}
          {{ quick_form(form) }}
      </div>
  {% endblock %}
  ```

  - 生成随机文件名

  ```python
  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():
      。。。
          # 提取文件后缀
          suffix = os.path.splitext(photo.filename)[1]
          # 生成随机文件名
          filename = random_string() + suffix
          # 保存文件
          photos.save(photo, name=filename)
      。。。
  ```

  - 生成缩略图:PIL模块(只支持py2,要支持py3需要安装pillow)

  ```python
  from PIL import Image

  @app.route(/upload/, methods=[GET, POST])
  def upload():
      ...
          # 拼接完整文件路径名
          pathname = os.path.join(app.config[UPLOADED_PHOTOS_DEST], filename)
          # 打开文件
          img = Image.open(pathname)
          # 设置大小
          img.thumbnail((64, 64))
          # 保存图片
          img.save(pathname)
      ...
  ```


### flask-mail

- 说明:专门用于邮件发送的扩展库,使用非常方便。

- 安装:`pip install flask-mail`

- 使用:

  ```python
  from flask_mail import Mail, Message
  import os

  # 邮件发送配置,一定要放在创建Mail对象之前
  app.config[MAIL_SERVER] = smtp.1000phone.com
  # 用户名
  app.config[MAIL_USERNAME] = lijie@1000phone.com
  # 密码
  app.config[MAIL_PASSWORD] = os.getenv(MAIL_PASSWORD, 123456)

  # 创建发送邮件的对象
  mail = Mail(app)

  @app.route(/send/)
  def send():
      # 创建邮件消息对象
      msg = Message(账户激活,
                    recipients=[shuai_fmzj@163.com],
                    sender=app.config[MAIL_USERNAME])
      msg.html = 恭喜你,中奖了!!!
      # 发送邮件
      mail.send(msg)
      return 邮件已发送
  ```

- 封装函数发送邮件

  ```python
  def send_mail(subject, to, template, *args, **kwargs):
      if isinstance(to, list):
          recipients = to
      elif isinstance(to, str):
          recipients = to.split(,)
      else:
          raise Exception(邮件接收者参数类型有误)
      # 创建邮件消息对象
      msg = Message(subject,
                    recipients=recipients,
                    sender=app.config[MAIL_USERNAME])
      # 将邮件模板渲染后作为邮件内容
      msg.html = render_template(template, *args, **kwargs)
      # 发送邮件
      mail.send(msg)
  ```

- 异步发送邮件

  ```python
  from flask import current_app

  # 异步发送邮件任务
  def async_send_mail(app, msg):
      # 邮件发送必须在程序上下文
      # 新的线程中没有上下文,因此需要手动创建
      with app.app_context():
          mail.send(msg)
          
  # 封装函数发送邮件
  def send_mail(subject, to, template, *args, **kwargs):
      if isinstance(to, list):
          recipients = to
      elif isinstance(to, str):
          recipients = to.split(,)
      else:
          raise Exception(邮件接收者参数类型有误)
      # 创建邮件消息对象
      msg = Message(subject,
                    recipients=recipients,
                    sender=app.config[MAIL_USERNAME])
      # 将邮件模板渲染后作为邮件内容
      msg.html = render_template(template, *args, **kwargs)
      # 异步发送邮件
      # current_app是app的代理对象
      # 根据代理对象current_app找到原始的app
      app = current_app._get_current_object()
      # 创建线程
      thr = Thread(target=async_send_mail, args=(app, msg))
      # 启动线程
      thr.start()
      # 返回线程
      return thr        
  ```


###环境变量

- windows:
  - 设置:`set 环境变量名=值`
  - 获取:`set 环境变量名`
- linux:
  - 导出:`export 环境变量名=值`
  - 获取:`echo $环境变量名`
- 代码:
  - `os.getenv(环境变量名, 123456)`

 

文件上传与邮件发送

标签:png   imp   smtp   函数   邮件   ade   rms   获取   contain   

原文地址:https://www.cnblogs.com/liangliangzz/p/10221980.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!