文件上传与邮件发送

# 文件上传与邮件发送### 原生实现- 模板文件 ```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)`

 

相关文章