1.添加一个模板文件html
<!DOCTYPE html>
<html>
<head>
<meta>
<title>文件上传</title>
</head>
<body>
{% if img_url %}
<img src="{{ img_url }}">
{% endif %}
<form>
<input>
<input>
</form>
</body>
</html>
2.添加视图函数
@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):
# 获取文件后缀
suffix = os.path.splitext(photo.filename)[-1]
# 随机生成文件名
photoname = random_string() + suffix
# 保存上传的文件
photo.save(os.path.join(app.config['UPLOAD_FOLDER'], photoname))
img_url = url_for('uploaded', filename=photoname)
return render_template('upload.html', img_url = img_url)
3.相关配置及函数
# 允许上传的文件后缀
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
# 获取上传文件的url
@app.route('/uploaded/<filename>')
def uploaded(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
# 生成随机字符串
def random_string(length = 32):
import random
base_str = 'abcdefghijklmnopqrstuvwxyz1234567890'
return ''.join([random.choice(base_str) for i in range(length)])
4.注意事项,文件上传失败时,应从哪些方面着手
1.表单的提交方法必须是POST
2.表单的enctype属性必须设置(multipart/form-data)
3.上传的字段类型必须为file, 并且必须有name属性
4.是否超过了允许的最大尺寸
5.文件的保存位置是否还有空间,是否有权限
5.生成缩略图(需要安装Pillow库)
# 保存上传的文件
photo.save(pathname)
# 生成缩略图
# 1.打开文件
img = Image.open(pathname)
# 2.重新设置尺寸
img.thumbnail((128, 128)) # 参数为元组,指定宽高
# 3.保存修改
img.save(pathname)
环境变量:好处是可以避免隐私信息公布于众(设置时注意等号两边不要加空格)。
windows配置
设置:set NAME=dandan
获取:set NAME
linux配置
导出:export NAME=dandan
获取:echo $NAME
代码获取
@app.route('/env/')
def env():
return os.environ.get('NAME', 'Ahh')
1.说明
在文件上传时,提供了很大的方便,比如文件类型的过滤、校验等
2.安装
pip install flask-upload
3.使用
from flask_uploads import UploadSet, IMAGES, configure_uploads, patch_request_class
# 上传文件的大小
app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 8
# 上传文件的保存位置
import os
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)
# html
<!DOCTYPE html>
<html>
<head>
<meta>
<title>文件上传</title>
</head>
<body>
{% if img_url %}
<img src="{{ img_url }}">
{% endif %}
<form>
<input>
<input>
</form>
</body>
</html>
1.flask-uploads配置同上
2.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,)])
submit = SubmitField('上传')
3.视图函数
# 随机生成文件名
def random_string(length = 32):
import random
base_str = '1234567890qwertyuiopasdfghjklmnbvcxz'
return ''.join([random.choice(base_str) for i in range(length)])
@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)
img_url = photos.url(filename)
return render_template('upload2.html', form=form, img_url=img_url)
4.模板文件
{% extends 'bootstrap/base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block content %}
<div>
{% if img_url %}
<img src="{{ img_url }}">
{% endif %}
{{ wtf.quick_form(form) }}
</div>
{% endblock %}
1.说明
是一个邮件发送的扩展库,使用非常方便
2.安装
pip install flask-mail
3.配置
from flask_mail import Mail, Message
# 配置一定要写在创建Mail对象之前,否则不起作用
# 邮箱服务器
import os
app.config['MAIL_SERVER'] = os.environ.get('MAIL_SERVER', 'smtp.163.com')
# 用户名
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME', 'xxx@163.com')
# 密码,密码有时是授权码
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD', 'xxxxxx')
# 创建对象
mail = Mail(app)
4.发送邮件
@app.route('/')
def hello_world():
# 创建邮件对象
msg = Message(subject='丹丹的测试邮件', recipients=['xxx@qq.com'], sender=app.config['MAIL_USERNAME'])
# 浏览器打开显示这个
msg.html = '<h1>Nice day</h1>'
# 终端打开显示这个
msg.body = 'Body'
mail.send(msg)
return '邮件已发送!'
5.封装函数,发送邮件
# 封装函数,发送邮件
def send_mail(to, subject, template, **kwargs):
# 创建邮件对象
msg = Message(subject=subject, recipients=to, sender=app.config['MAIL_USERNAME'])
# 浏览器打开显示这个
msg.html = '<b>Nice day</b>'
# 终端打开显示这个
msg.body = 'Nice day'
mail.send(msg)
6.异步发送邮件
# 异步发送邮件
def async_send_mail(app, msg):
# 发送邮件需要程序上下文,新的线程中没有上下文,需要手动创建
with app.app_context():
# 发送邮件
mail.send(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)
# mail.send(msg)
# 创建线程
thr = Thread(target=async_send_mail, args=[current_app, msg])
# 启动线程
thr.start()
return thr