在 Flask 中实现文件下载功能
在 Flask 中实现文件下载功能可以通过多种方式实现,以下是几种常见的方法:

使用 send_file 函数(推荐)
这是 Flask 提供的最简单、最直接的方法:
from flask import Flask, send_file
import os
app = Flask(__name__)
@app.route('/download/<filename>')
def download_file(filename):
# 构建文件路径
file_path = os.path.join('downloads', filename)
# 检查文件是否存在
if not os.path.exists(file_path):
return "File not found", 404
# 发送文件
return send_file(
file_path,
as_attachment=True, # 作为附件下载
download_name=filename # 设置下载时的文件名
)
if __name__ == '__main__':
app.run(debug=True)
使用 send_from_directory 函数
如果你有专门的下载目录,可以使用这个函数:
from flask import Flask, send_from_directory
import os
app = Flask(__name__)
@app.route('/download/<path:filename>')
def download_file(filename):
directory = 'downloads'
return send_from_directory(directory, filename, as_attachment=True)
if __name__ == '__main__':
app.run(debug=True)
手动实现文件下载
如果你需要更多的控制,可以手动实现:
from flask import Flask, Response
import os
app = Flask(__name__)
@app.route('/download/<filename>')
def download_file(filename):
file_path = os.path.join('downloads', filename)
if not os.path.exists(file_path):
return "File not found", 404
def generate():
with open(file_path, 'rb') as f:
while True:
chunk = f.read(8192)
if not chunk:
break
yield chunk
return Response(
generate(),
mimetype='application/octet-stream',
headers={
'Content-Disposition': f'attachment; filename="{filename}"'
}
)
if __name__ == '__main__':
app.run(debug=True)
高级用法
设置下载时的文件名
return send_file(
file_path,
as_attachment=True,
download_name='new_name.pdf' # 下载时显示的文件名
)
处理大文件流式下载
对于大文件,建议使用流式传输:

from flask import Flask, Response
import os
app = Flask(__name__)
@app.route('/download/<filename>')
def download_large_file(filename):
file_path = os.path.join('downloads', filename)
if not os.path.exists(file_path):
return "File not found", 404
def generate():
with open(file_path, 'rb') as f:
while True:
chunk = f.read(8192) # 8KB chunks
if not chunk:
break
yield chunk
return Response(
generate(),
mimetype='application/octet-stream',
headers={
'Content-Disposition': f'attachment; filename="{filename}"'
}
)
需要认证的文件下载
from flask import Flask, send_file, request, abort
from functools import wraps
app = Flask(__name__)
def auth_required(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
abort(401)
return f(*args, **kwargs)
return decorated
def check_auth(username, password):
# 这里应该是实际的认证逻辑
return username == 'admin' and password == 'secret'
@app.route('/download/<filename>')
@auth_required
def download_protected_file(filename):
file_path = os.path.join('downloads', filename)
if not os.path.exists(file_path):
abort(404)
return send_file(file_path, as_attachment=True)
注意事项
-
文件路径安全:确保用户提供的文件名不会导致路径遍历攻击,使用
os.path.join和os.path.abspath来验证路径。 -
性能考虑:对于大文件,使用流式传输避免内存问题。
-
MIME 类型:Flask 会尝试自动检测文件的 MIME 类型,但你可以手动指定:
return send_file(file_path, mimetype='application/pdf')
-
缓存控制:可以添加缓存头控制浏览器行为:
return send_file( file_path, as_attachment=True, cache_timeout=0 # 禁用缓存 )
方法可以根据你的具体需求选择使用,send_file 是最常用和推荐的方式。
