Dropzone.js是一个提供文件上传、验证、预览、上传进度条等功能的JavaScript库。Flask-Dropzone在模板中提供了一些方法来帮助你创建上传区域,引入相关资源。你只需要添加一些配置就可以实现上传类型的过滤,文件大小限制,上传后跳转等功能。当然,你还要自己编写视图函数来处理和保存文件,并进行服务器端的二次验证。如果你不熟悉服务器端的上传文件处理,可以考虑浏览一下这篇
《Flask文件上传(一):原生实现》。
《Flask Web开发实战》中的第3个示例程序(
图片社交程序Albumy)使用了这个扩展。
用法介绍
安装
$ pip install flask-dropzone复制代码
初始化
和其他扩展类似,你可以通过实例化Dropzone类,并传入程序实例app进行初始化:
from flask_dropzone import Dropzone
app = Flask(__name__)
dropzone = Dropzone(app)复制代码
在使用工厂函数创建程序实例时,你也可以使用init_app()方法:
from flask_dropzone import Dropzone
dropzone = Dropzone()
def create_app():
app = Flask(__name__)
dropzone.init_app(app)
return app复制代码
引入Dropzone.js资源
你需要自己手动编写引入Dropzone.js的CSS和JavaScript资源的语句。在开发时,或对于玩具项目,你可以可以使用Flask-Dropzone提供的两个快捷方法:
<head>
...
{{ dropzone.load_css() }}
</head>
<body>
...
{{ dropzone.load_js() }}
</body>复制代码
创建并美化上传区域
如果你不需要对上传区域的样式有太多控制,那么你只需要在想要渲染上传区域的地方使用dropzone.create()方法:
{{ dropzone.create(action='处理上传文件的路由URL') }}复制代码
记得把action参数的值更改成你要处理文件上传的的URL。你可以使用dropzone.style()方法为上传区域添加简单的自定义样式:
<head>
... <!-- 在引入Dropzone.js的CSS文件后调用style()方法 -->
{{ dropzone.style('border: 2px dashed #0087F7; margin: 10%') }}
</head>复制代码
在服务器端处理并保存上传文件
当文件被拖拽到上传区域,或是点击上传区域选择上传文件后,这些文件会以AJAX请求的形式发送到你在dropzone.create()方法中使用action参数传入的URL。我们需要在服务器端创建对应的视图函数来处理这些请求,下面是一个最基本的示例:
import os
from flask import Flask, request
from flask_dropzone import Dropzone
app = Flask(__name__)
dropzone = Dropzone(app)
@app.route('/uploads', methods=['GET', 'POST'])
def upload():
if request.method == 'POST': # 如果请求类型为POST,说明是文件上传请求
f = request.files.get('file') # 获取文件对象
f.save(os.path.join('the/path/to/save', f.filename)) # 保存文件
return 'upload template' # 渲染上传页面复制代码
上传完成后重定向
这里需要注意的是,因为Dropzone.js通过AJAX请求提交文件,所以你没法在保存文件后将页面重定向。对于这个问题,你可以使用配置变量DROPZONE_REDIRECT_VIEW设置上传完成后跳转到的目标端点,或是添加一个按钮让用户自己点击进行跳转。
服务器端验证
尽管Dropzone.js可以在前端对用户提交的文件进行验证,但为了安全考虑,我们仍然需要在服务器端进行二次验证。在服务器端验证时,如果验证出错,我们不能像往常那样使用flash()函数“闪现”错误消息,因为AJAX请求接受到响应后并不会重载页面,所以不会显示通过flash()函数发送的消息。正确的做法是返回400错误响应,使用错误消息作为响应的主体。下面是一个简单的进行服务器端验证并返回错误消息得示例:
@app.route('/', methods=['POST', 'GET'])
def upload():
if request.method == 'POST':
f = request.files.get('file')
if f.filename.split('.')[1] != 'png':
return 'PNG only!', 400 # return the error message, with a proper 4XX code
f.save(os.path.join('the/path/to/save', f.filename))
return render_template('index.html')复制代码
在上面的代码中,我们验证图片是不是png格式,如果不是就返回一个错误提示,在服务器端会在图片下面看到我们返回的错误消息:
完整的配置列表
Flask-Dropzone提供了丰富的配置变量,你可以使用它们对Dropzone.js进行各类配置。很遗憾掘金的编辑器不支持表格,所以这里只能插入一张图片,如果你需要文本,可以访问
这篇文章。
这些配置的用法你可以参考Flask-Drozone的
文档或是
示例程序了解,这里我们仅简单介绍一下对文件类型进行过滤的设置方法。
设置文件类型过滤
Flask-Dropzone内置了一些文件类型(通过MIME定义),可选的值和对应的文件类型如下所示:
-
default:默认值,运行所有类型
-
image:图片
-
audio:音频
-
video:视频
-
text:文本
-
app:程序
你需要为DROPZONE_ALLOWED_FILE_TYPE设置对应的值,比如下面设置仅允许上传图片:
app.config['DROPZONE_ALLOWED_FILE_TYPE'] = 'image'复制代码
如果你想要自己定义允许的文件类型列表,那么你需要将DROPZONE_ALLOWED_FILE_CUSTOM设置True,然后传入一个包含允许的文件后缀名列表组成的字符串给DROPZONE_ALLOWED_FILE_TYPE变量,使用逗号分隔多个后缀名,比如:
app.config['DROPZONE_ALLOWED_FILE_CUSTOM'] = True
app.config['DROPZONE_ALLOWED_FILE_TYPE'] = 'image/*, .pdf, .txt'复制代码
对于平行上传、CSRF保护等内容的具体实现方法你可以参考
文档了解。不过,这个项目目前还没有创建完善的文档,暂时只是写到README里,如果你发现了英文语法或拼写错误,欢迎指正,同时也欢迎为项目贡献代码。
示例程序
Flask-Dropzone的Git仓库中的
examples目录下包含4个示例程序,分别演示了基本用法、CSRF保护、平行上传和上传完成后跳转四个功能。
另外,
helloflask仓库里在demos/form目录下的示例程序也包含一个Flask-Dropzone使用示例。
相关链接