文件上传与邮件发送
原生上传文件
-
添加一个模板文件
<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>
-
添加视图函数
@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)
-
相关配置及函数
# 允许上传的文件后缀
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)
-
注意事项,文件上传失败时,应从哪些方面着手
1.表单的提交方法必须是POST
2.表单的enctype属性必须设置为multipart/form-data
3.上传的字段类型必须为file,并且必须有name属性
4.是否超过运行的最大尺寸
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
-
说明:在文件上传时,提供了很大的方便,如:文件类型的过滤,校验等
-
安装:
pip install flask-uploads
-
使用:
相关配置:
# 上传文件的大小
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
完整的文件上传
-
flask-uploads配置同上
-
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('上传')
-
视图函数:
@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)
-
模板文件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
-
说明:是一个邮件发送的扩展库,使用非常方便
-
安装:
pip install flask-mail
-
配置:一定要写在创建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)
-
发送邮件
@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 '邮件已发送'
-
封装函数,发送邮件
# 封装函数,发送邮件
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 '邮件已发送'
-
异步发送邮件
# 异步发送邮件
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
扩展
环境变量:好处是可以避免隐私的信息公布于众
-
windows配置
设置:set NAME=xiaoming
获取:set NAME
-
linux配置
导出:export NAME=xiaoming
获取:echo $NAME
-
代码获取
import os
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY') or '123456'
os.environ.get('NAME', 'default')