You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask中send_from_directory下载文件重复覆盖,Safari下如何解决?

解决Flask中Safari下载文件覆盖的问题

问题根源

Firefox会自动检测本地同名下载文件并生成带序号的副本,但Safari默认会直接覆盖,这是浏览器行为差异导致的。我们可以通过Flask端调整响应头或文件名策略来解决。

两种可行方案

方案1:通过响应头触发Safari自动生成序号

这种方案不需要服务器记录用户状态,通过设置正确的响应头让Safari识别每次下载为新请求,从而触发自动命名逻辑:

from flask import send_from_directory, make_response
import os
import urllib.parse

@app.route('/uploads/<name>')
def download_file(name):
    uploads = app.config["UPLOAD_FOLDER"]
    file_path = os.path.join(uploads, name)
    
    # 编码文件名以支持特殊字符
    encoded_name = urllib.parse.quote(name)
    response = make_response(send_from_directory(uploads, name))
    
    # 符合RFC 5987标准的Content-Disposition头,兼容Safari
    response.headers["Content-Disposition"] = f"attachment; filename=\"{name}\"; filename*=UTF-8''{encoded_name}"
    
    # 禁用缓存,确保Safari每次都处理为新下载
    response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
    response.headers["Pragma"] = "no-cache"
    response.headers["Expires"] = "0"
    
    return response

方案2:服务器端生成带序号的文件名

如果需要完全控制文件名,避免依赖浏览器行为,可以结合用户会话记录下载次数,动态生成带序号的文件名:

from flask import send_from_directory, session
import os

@app.route('/uploads/<name>')
def download_file(name):
    uploads = app.config["UPLOAD_FOLDER"]
    # 用会话记录当前用户对该文件的下载次数
    file_count_key = f"download_counter_{name}"
    current_count = session.get(file_count_key, 0) + 1
    session[file_count_key] = current_count
    
    # 拆分文件名和后缀,生成带序号的新文件名
    file_base, file_ext = os.path.splitext(name)
    if current_count > 1:
        new_filename = f"{file_base}-{current_count}{file_ext}"
    else:
        new_filename = name
    
    # 返回文件,指定新的附件文件名
    return send_from_directory(uploads, name, as_attachment=True, attachment_filename=new_filename)

方案对比

  • 方案1:无需用户登录/会话,依赖浏览器行为调整,适合匿名用户场景,能让Safari自动生成类似foo.txt-2的序号文件。
  • 方案2:完全由服务器控制文件名,彻底避免覆盖,但需要依赖用户会话,匿名用户会话过期后计数会重置。

内容的提问来源于stack exchange,提问作者bradenjoshua

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 21:47:28