<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Flask-Dropzone &#8211; 李辉 / Grey Li</title>
	<atom:link href="https://greyli.com/tag/flask-dropzone/feed/" rel="self" type="application/rss+xml" />
	<link>https://greyli.com</link>
	<description>一个编程和写作爱好者的在线记事本</description>
	<lastBuildDate>Sat, 15 Nov 2025 10:55:15 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.9.26</generator>

<image>
	<url>https://greyli.com/wp-content/uploads/2025/03/avatar-500-compressed-144x144.jpg</url>
	<title>Flask-Dropzone &#8211; 李辉 / Grey Li</title>
	<link>https://greyli.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Flask-Dropzone：为你的Flask程序添加文件上传功能</title>
		<link>https://greyli.com/flask-dropzone/</link>
		<comments>https://greyli.com/flask-dropzone/#comments</comments>
		<pubDate>Wed, 22 Feb 2017 10:15:30 +0000</pubDate>
		<dc:creator><![CDATA[李辉]]></dc:creator>
				<category><![CDATA[计算机与编程]]></category>
		<category><![CDATA[Flask]]></category>
		<category><![CDATA[Flask-Dropzone]]></category>
		<category><![CDATA[文件上传]]></category>

		<guid isPermaLink="false">http://greyli.com/?p=1382</guid>
		<description><![CDATA[这篇文章属于“Flask常用扩展介绍系列”，这个系列的文章目录索引可以在《Flask常用扩展介绍系列文章索引》 [&#8230;]]]></description>
				<content:encoded><![CDATA[<div class="Editable-unstyled" data-block="true" data-editor="d10kp" data-offset-key="5ulkm-0-0">
<div class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr" data-offset-key="5ulkm-0-0"><span data-offset-key="5ulkm-0-0"><span data-text="true">这篇文章属于“Flask常用扩展介绍系列”，这个系列的文章目录索引可以在</span></span><a class="Link ztext-link" href="https://zhuanlan.zhihu.com/p/39183712" target="_blank" rel="noopener" data-offset-key="5ulkm-1-0" data-editable="true"><span data-offset-key="5ulkm-1-0"><span data-text="true">《Flask常用扩展介绍系列文章索引》</span></span></a><span data-offset-key="5ulkm-2-0"><span data-text="true">看到。</span></span></div>
<div class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr" data-offset-key="5ulkm-0-0"> </div>
</div>
<p>某天在Stack Overflow上看到一个<a href="http://stackoverflow.com/questions/42101786/dropzone-js-prevents-flask-from-rendering-template/42264730#42264730" target="_blank" rel="noopener">关于Dropzone.js的问题</a>，就去研究了一下，写了一个回答，顺便写了一个小demo。我发现，如果有一个集成Dropzone.js到Flask，并且简化设置步骤的扩展，肯定要比其他上传方式简单的多——于是就有了<a href="https://github.com/greyli/flask-dropzone">Flask-Dropzone</a>。</p>
<p>Flask-Dropzone在模板中提供了一些方法来帮助你创建上传区域，引入相关资源。你只需要添加一些配置就可以实现上传类型的过滤，文件大小限制，上传后跳转等功能。当然，你还要自己编写视图函数来处理和保存文件，并进行服务器端的二次验证。</p>
<blockquote>
<p><a href="https://zhuanlan.zhihu.com/p/29907260">《Flask Web开发实战》</a>中的第3个示例程序（<a href="https://zhuanlan.zhihu.com/p/38342129">图片社交程序Albumy</a>）使用了这个扩展。</p>
</blockquote>
<h2>用法说明</h2>
<h3>安装</h3>
<pre class="">$ pip install flask-dropzone</pre>
<h3>初始化</h3>
<p>和其他扩展类似，你可以通过实例化Dropzone类，并传入程序实例app进行初始化：</p>
<pre class="">from flask_dropzone import Dropzone

app = Flask(__name__)
dropzone = Dropzone(app)
</pre>
<p>在使用工厂函数创建程序实例时，你也可以使用init_app()方法：</p>
<pre><code>from flask_dropzone import Dropzone

dropzone = Dropzone()

def create_app():
    app = Flask(__name__)
    dropzone.init_app(app)
    return app</code></pre>
<h3>引入Dropzone.js资源</h3>
<p>你需要自己手动编写引入Dropzone.js的CSS和JavaScript资源的语句。在开发时，或对于玩具项目，你可以可以使用Flask-Dropzone提供的两个快捷方法：</p>
<pre><code>&lt;head&gt;
    ...
    {{ dropzone.load_css() }}
&lt;/head&gt;
&lt;body&gt;
    ...
    {{ dropzone.load_js() }}
&lt;/body&gt;
</code></pre>
<h3>创建并美化上传区域</h3>
<p>如果你不需要对上传区域的样式有太多控制，那么你只需要在想要渲染上传区域的地方使用dropzone.create()方法：</p>
<pre><code>{{ dropzone.create(action='处理上传文件的路由URL') }}</code></pre>
<p>记得把action的值更改成你要处理文件上传的的URL。你可以使用style()方法为上传区域添加简单的自定义样式：</p>
<pre class="">&lt;head&gt;
...  &lt;!-- 在引入Dropzone.js的CSS文件后调用style()方法 --&gt;
{{ dropzone.style('border: 2px dashed #0087F7; margin: 10%') }}
&lt;/head&gt;</pre>
<p class="">上传区域的截图示例如下所示：</p>
<div id="attachment_1380" style="width: 1125px" class="wp-caption alignnone"><a href="http://greyli.com/wp-content/uploads/2016/05/bg.jpg" rel="attachment wp-att-1380"><img class="wp-image-1380 size-full" src="http://greyli.com/wp-content/uploads/2016/05/bg.jpg" alt="Flask-Dropzone上传截图" width="1115" height="790" srcset="https://greyli.com/wp-content/uploads/2016/05/bg.jpg 1115w, https://greyli.com/wp-content/uploads/2016/05/bg-150x106.jpg 150w, https://greyli.com/wp-content/uploads/2016/05/bg-300x213.jpg 300w, https://greyli.com/wp-content/uploads/2016/05/bg-1024x726.jpg 1024w, https://greyli.com/wp-content/uploads/2016/05/bg-624x442.jpg 624w" sizes="(max-width: 1115px) 100vw, 1115px" /></a><p class="wp-caption-text">Flask-Dropzone上传截图</p></div>
<h3>在服务器端处理并保存上传文件</h3>
<p>当文件被拖拽到上传区域，或是点击上传区域选择上传文件后，这些文件会以AJAX请求的形式发送到你在dropzone.create()方法中使用action参数传入的URL。我们需要在服务器端创建对应的视图函数来处理这些请求，下面是一个最基本的示例：</p>
<pre class="">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'  # 渲染上传页面</pre>
<p>&nbsp;</p>
<h3>上传完成后重定向</h3>
<p>这里需要注意的是，因为Dropzone.js通过AJAX请求提交文件，所以你没法在保存文件后将页面重定向。对于这个问题，你可以使用配置变量DROPZONE_REDIRECT_VIEW设置上传完成后跳转到的目标端点，或是添加一个按钮让用户自己点击进行跳转。</p>
<h3>服务器端验证</h3>
<p>尽管Dropzone.js可以在前端对用户提交的文件进行验证，但为了安全考虑，我们仍然需要在服务器端进行二次验证。在服务器端验证时，如果验证出错，我们不能像往常那样使用flash()函数“闪现”错误消息，因为AJAX请求接受到响应后并不会重载页面，所以不会显示通过flash()函数发送的消息。正确的做法是返回400错误响应，使用错误消息作为响应的主体。下面是一个简单的进行服务器端验证并返回错误消息得示例：</p>
<pre class="">@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')</pre>
<p>在上面的代码中，我们验证图片是不是png格式，如果不是就返回一个错误提示，在服务器端会在图片下面看到我们返回的错误消息：</p>
<p><img title="" src="https://github.com/greyli/flask-dropzone/raw/master/resources/validation.png" alt="" /></p>
<p>&nbsp;</p>
<h2> </h2>
<h2><a id="configuration"></a>完整的配置列表</h2>
<p>Flask-Dropzone提供了丰富的配置变量，你可以使用它们对Dropzone.js进行各类配置。</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Default Value</th>
<th>Info</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>DROPZONE_SERVE_LOCAL</code>  </td>
<td><code>False</code>      </td>
<td>使用Flask-Dropzone提供的load_css()和load_js()方法时，这个变量设置是否使用内置的本地资源，默认从CND加载</td>
</tr>
<tr>
<td><code>DROPZONE_MAX_FILE_SIZE</code></td>
<td>3</td>
<td>允许的文件最大值，单位为MB</td>
</tr>
<tr>
<td><code>DROPZONE_INPUT_NAME</code></td>
<td><code>file</code></td>
<td><code><span style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;">上传字段的name值</span></code></td>
</tr>
<tr>
<td><code>DROPZONE_ALLOWED_FILE_CUSTOM</code></td>
<td><code>False</code></td>
<td>是否使用自定义文件类型允许规则，具体见后面</td>
</tr>
<tr>
<td><code>DROPZONE_ALLOWED_FILE_TYPE</code></td>
<td><code>'default'</code></td>
<td>允许的文件类型，具体见后面</td>
</tr>
<tr>
<td><code>DROPZONE_MAX_FILES</code></td>
<td>&#8216;null&#8217;</td>
<td>一次可以上传的文件数量最大值</td>
</tr>
<tr>
<td><code>DROPZONE_DEFAULT_MESSAGE</code></td>
<td>&#8220;Drop files here to upload&#8221;</td>
<td>上传区域显示的提示文字</td>
</tr>
<tr>
<td><code>DROPZONE_INVALID_FILE_TYPE</code></td>
<td>&#8220;You can&#8217;t upload files of this type.&#8221;</td>
<td>文件类型错误的错误消息</td>
</tr>
<tr>
<td><code>DROPZONE_FILE_TOO_BIG</code></td>
<td>&#8220;File is too big {{filesize}}. Max filesize: {{maxFilesize}}MiB.&#8221;</td>
<td>文件太大时显示的错误消息</td>
</tr>
<tr>
<td><code>DROPZONE_SERVER_ERROR</code></td>
<td>&#8220;Server error: {{statusCode}}&#8221;</td>
<td>服务器错误的错误消息</td>
</tr>
<tr>
<td><code>DROPZONE_BROWSER_UNSUPPORTED</code></td>
<td>&#8220;Your browser does not support drag&#8217;n&#8217;drop file uploads.&#8221;</td>
<td>浏览器不支持的错误消息</td>
</tr>
<tr>
<td><code>DROPZONE_MAX_FILE_EXCEED</code></td>
<td>&#8220;Your can&#8217;t upload any more files.&#8221;</td>
<td>超过最大文件数量限制的错误消息</td>
</tr>
<tr>
<td><code>DROPZONE_UPLOAD_MULTIPLE</code></td>
<td><code>False</code></td>
<td>是否在单个请求中发送多个文件，默认一个请求发送一个文件</td>
</tr>
<tr>
<td><code>DROPZONE_PARALLEL_UPLOADS</code></td>
<td>2</td>
<td>当DROPZONE_UPLOAD_MULTIPLE设为True时，设置单个请求包含的文件数量</td>
</tr>
<tr>
<td><code>DROPZONE_REDIRECT_VIEW</code></td>
<td><code>None</code></td>
<td>上传完成后重定向的模板端点</td>
</tr>
<tr>
<td><code>DROPZONE_ENABLE_CSRF</code></td>
<td><code>False</code></td>
<td>是否开启CSRF保护</td>
</tr>
</tbody>
</table>
<p>这些配置的用法你可以参考Flask-Drozone的<a href="https://github.com/greyli/flask-dropzone">文档</a>或是<a href="https://github.com/greyli/flask-dropzone/tree/master/examples" target="_blank" rel="noopener">示例程序</a>了解，这里我们仅简单介绍一下对文件类型进行过滤的设置方法。</p>
<h3>设置文件类型过滤</h3>
<p>Flask-Dropzone内置了一些文件类型（通过MIME定义），可选的值和对应的文件类型如下所示：</p>
<ul>
<li>default：默认值，运行所有类型</li>
<li>image：图片</li>
<li>audio：音频</li>
<li>video：视频</li>
<li>text：文本</li>
<li>app：程序</li>
</ul>
<p>你需要为DROPZONE_ALLOWED_FILE_TYPE设置对应的值，比如下面设置仅允许上传图片：</p>
<div>
<pre class="">app.config['DROPZONE_ALLOWED_FILE_TYPE'] = 'image'</pre>
</div>
<p>如果你想要自己定义允许的文件类型列表，那么你需要将DROPZONE_ALLOWED_FILE_CUSTOM设置True，然后传入一个包含允许的文件后缀名列表组成的字符串给DROPZONE_ALLOWED_FILE_TYPE变量，使用逗号分隔多个后缀名，比如：</p>
<div>
<pre class="">app.config['DROPZONE_ALLOWED_FILE_CUSTOM'] = True
app.config['DROPZONE_ALLOWED_FILE_TYPE'] = 'image/*, .pdf, .txt'</pre>
</div>
<p>对于平行上传、CSRF保护等内容的具体实现方法你可以参考<a href="https://github.com/greyli/flask-dropzone">文档</a>了解。不过，这个项目目前还没有创建完善的文档，暂时只是写到README里，如果你发现了英文语法或拼写错误，欢迎指正，同时也欢迎为项目贡献代码。</p>
<h2>示例程序</h2>
<p>Flask-Dropzone的Git仓库中的examples目录下包含4个示例程序，分别演示了基本用法、CSRF保护、平行上传和上传完成后跳转四个功能。</p>
<p>源码可以在这里找到：<a href="https://github.com/greyli/flask-dropzone/tree/master/examples" target="_blank" rel="noopener">https://github.com/greyli/flask-dropzone/tree/master/examples</a></p>
<div>
<div>另外，<a href="https://github.com/greyli/helloflask">helloflask仓库</a>里在demos/form目录下的示例程序也包含一个Flask-Dropzone使用示例。</div>
</div>
<h2>相关链接</h2>
<ul>
<li>文档：<a href="https://flask-dropzone.readthedocs.io/en/latest/">https://flask-dropzone.readthedocs.io/en/latest/</a></li>
<li>
<div>源码：<a href="https://github.com/greyli/flask-dropzone">https://github.com/greyli/flask-dropzone</a></div>
</li>
<li>
<div>PyPI：<a href="https://pypi.python.org/pypi/Flask-Dropzone">https://pypi.python.org/pypi/Flask-Dropzone</a></div>
</li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>https://greyli.com/flask-dropzone/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>
