Flask-文件上传
flash消息
- 
说明: - 当用户的状态发生改变时,需要给与提示,警告等信息;通常都是以弹窗的形式出现,指引用户操作。
 
- 
函数: - 
flash:将指定的内容保存起来,用在视图函数中1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14from flask import Flask, render_template, redirect, url_for, session, flash, get_flashed_messages 
 def index():
 form = NameForm()
 if form.validate_on_submit():
 last_name = session.get('username', None)
 if last_name and last_name != form.name.data:
 flash('大哥,又换签名了?')
 session['username'] = form.name.data
 return redirect(url_for('index'))
 name = session.get('username', None)
 return render_template('form.html', form=form, name=name)
 - 
get_flashed_messages:获取保存的消息,用在模板文件中1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15{% extends 'bootstrap/base.html' %} 
 {% import 'bootstrap/wtf.html' as wtf %}
 {% block content %}
 <div class="container">
 {% for message in get_flashed_messages() %}
 <div class="alert alert-warning alert-dismissible" role="alert">
 <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span>
 </button>
 {{ message }}
 </div>
 {% endfor %}
 </div>
 {% endblock %}
- 
提示:建议粘贴一个可消失的警告框 
 
- 
flask-moment
- **说明:**是一个将时间本地化显示的扩展库,使用非常简单
- 安装:pip install flask-moment
- 使用:
- 视图函数:导入类库,创建对象1 
 2
 3
 4
 5
 6
 7
 8
 9
 10from flask_moment import Moment 
 moment = Moment(app)
 @app.route('/mom/')
 def mom():
 from datetime import datetime, timedelta
 t = datetime.utcnow() + timedelta(seconds=-60)
 return render_template('mom.html', t=t)
- 模板文件:加载moment.js文件,依赖jQuery1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19{# 加载jQuery #} 
 {{ moment.include_jquery() }}
 {# 加载moment.js文件,依赖jQuery #}
 {{ moment.include_moment() }}
 {# 设置语言为中文 #}
 {{ moment.locale('zh-CN') }}
 {# 简化版本的格式化显示 #}
 <div>时间:{{ moment(t).format('LLLL') }}</div>
 <div>时间:{{ moment(t).format('LLL') }}</div>
 <div>时间:{{ moment(t).format('LL') }}</div>
 <div>时间:{{ moment(t).format('L') }}</div>
 {# 自定义显示 #}
 <div>时间:{{ moment(t).format('YYYY-MM-DD') }}</div>
 {# 时间差 #}
 <div>发表于:{{ moment(t).fromNow() }}</div>
 
- 视图函数:导入类库,创建对象
- 时间本地化操作:
- 显示时间:moment(t).format('字符串')
- 时间差:moment(t).fromNow()
 
- 显示时间:
- moment官网
原生的文件上传
- 添加模板文件,书写一个表单,表单中添加file字段1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 <html lang="en">
 <head>
 <meta charset="UTF-8">
 <title>文件上传</title>
 </head>
 <body>
 <form method="post" action="" enctype="multipart/form-data">
 <input type="file" name="photo">
 <input type="submit" value="上传">
 </form>
 </body>
 </html>
- 视图函数中根据请求类型判断是否成功提交,然后提取(request.files)上传信息1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44from flask import Flask, request, render_template 
 from flask_script import Manager
 import os
 # 允许上传的文件后缀
 ALLOWED_EXTENSION = set(['png', 'jpg', 'jpeg', 'gif'])
 app = Flask(__name__)
 # 配置上传文件保存位置
 app.config['UPLOAD_FOLDER'] = os.getcwd()
 # 允许上传的文件大小
 app.config['MAX_CONTENT_LENGTH'] = 1024 * 2
 manager = Manager(app)
 # 检测上传的文件是否是允许的后缀
 def allowed_file(filename):
 return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSION
 def index():
 return '文件上传'
 def upload():
 if request.method == 'POST':
 # 获取上传文件对象
 file = request.files.get('photo')
 # 类型判断
 if file and allowed_file(file.filename):
 # 拼接文件路径名
 pathname = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
 # 保存文件
 file.save(pathname)
 return '上传成功!'
 else:
 return '上传失败'
 return render_template('upload.html')
 if __name__ == '__main__':
 manager.run()
- **安全检查:**文件大小,文件后缀
- **练习:**保存上传文件时使用随机的文件名
- **总结:**文件上传注意事项
- 表单提交方法必须是POST
- 表单必须设置enctype="multipart/form-data"
- 上传文件的字段必须为file,必须有name属性
- 是否超过了允许的最大尺寸
- 上传文件的临时保存目录是否有权限,是否有空间
 
flask-uploads
- 
**说明:**文件上传的扩展的库,提供了类型的限定,校验等功能 
- 
安装: pip install flask-uploads
- 
使用:- 
创建上传集合对象(UploadSet)1 
 2
 3
 4from flask_uploads import UploadSet, IMAGES, configure_uploads, patch_request_class 
 # 创建上传对象,指定名称及过滤的文件类型
 photos = UploadSet('photos', IMAGES)
- 
配置上传对象1 
 2# 配置上传对象 
 configure_uploads(app, photos)
- 
设置上传文件尺寸1 
 2
 3
 4
 5# 允许的HTTP请求的大小 
 app.config['MAX_CONTENT_LENGTH'] = 1024*1024*128
 # 设置文上传大小,默认为64M,要比HTTP最大请求允许的尺寸小
 # 设置为None时,MAX_CONTENT_LENGTH配置生效
 patch_request_class(app, size=1024 * 1024 * 2)
- 
配置上传文件保存目录1 
 2# 配置文件保存位置 
 app.config['UPLOADED_PHOTOS_DEST'] = os.getcwd()
- 
保存上传文件photo.save()1 
 2# 保存上传文件并获取上传名 
 filename = photos.save(request.files['photo'])
- 
获取URL:photos.url(filename)1 
 2# 获取上传文件的URL 
 img_url = photos.url(filename)
 
- 
- 
生成随机文件名:random_string1 
 2
 3
 4
 5# 生成随机字符创 
 def random_string(length=32):
 import random
 base_str = 'abcdefghijklmnopqrstuvwsyz1234567890'
 return ''.join(random.choice(base_str) for i in range(length))
综合上传
- flask-uploads
- flask-wtf
- flask-bootstrap
- 生成随机的文件名
- 生成缩略图pip install pillow
- flash
- 
示例: - 
视图函数 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68from flask import Flask, render_template, flash, get_flashed_messages 
 from flask_script import Manager
 from flask_bootstrap import Bootstrap
 from flask_uploads import UploadSet, IMAGES, configure_uploads
 from flask_wtf import FlaskForm
 from wtforms import SubmitField
 from flask_wtf.file import FileField, FileRequired, FileAllowed
 import os
 # PIL只支持Python2.x,开源社区维护了pillow使之支持Python3.x
 from PIL import Image
 app = Flask(__name__)
 app.config['SECRET_KEY'] = '123456'
 app.config['UPLOADED_PHOTOS_DEST'] = os.getcwd()
 manager = Manager(app)
 bootstrap = Bootstrap(app)
 photos = UploadSet('photos', IMAGES)
 configure_uploads(app, photos)
 # 文件上传表单类
 class UploadForm(FlaskForm):
 photo = FileField('上传头像', validators=[FileRequired('文件未选择'), FileAllowed(photos, message='只能上传图片文件')])
 submit = SubmitField('上传')
 def random_string(length=32):
 import random
 base_str = 'abcdefghijklmnopqrstuvwxyz1234567890'
 return ''.join(random.choice(base_str) for i in range(length))
 def index():
 return '完整的文件上传'
 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)
 # 保存flush消息
 flash('头像已上传成功')
 return render_template('upload.html', form=form, img_url=img_url)
 if __name__ == "__main__":
 manager.run()
- 
模板文件 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24{% extends 'bootstrap/base.html' %} 
 {% import 'bootstrap/wtf.html' as wtf %}
 {% block title %}完整的文件上传{% endblock %}
 {% block content %}
 {% for message in get_flashed_messages() %}
 <div class="alert alert-success alert-dismissible" role="alert">
 <button type="button" class="close" data-dismiss="alert" aria-label="Close">
 <span aria-hidden="true">×</span>
 </button>
 {{ message }}
 </div>
 {% endfor %}
 {% if img_url %}
 <img src="{{ img_url }}" alt="头像">
 {% endif %}
 <div class="container">
 {{ wtf.quick_form(form) }}
 </div>
 {% endblock %}
 
-