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
文件,依赖jQuery
1
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_string
1
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 %}
-