Flask路由打包Azure存储文件共享文件并返回Zip响应遇问题
Flask Azure文件共享批量打包下载问题修复
原代码存在的核心问题
- 临时文件提前被删除:
shutil.rmtree(temp_dir)在send_file之后立即执行,但Flask的send_file是延迟响应机制,此时文件已被删除,前端会收到空文件或下载失败。 - 未过滤目录:遍历文件共享时会包含目录条目,用
get_file_client处理目录会触发错误,导致打包流程中断。 - 临时目录并发冲突:直接使用固定路径
/tmp,多请求同时触发时会互相覆盖文件,导致打包内容混乱。 - 缺乏异常处理:下载或打包过程中出错时,临时文件无法自动清理,会持续占用服务器空间。
修正后的代码
import os import tempfile from zipfile import ZipFile from flask import send_file from azure.storage.fileshare import ShareClient @files_blueprint.route('/download/all', methods=['GET']) def download_all(): print("-------------downloading all files-----------") # 初始化文件共享客户端 share_client = ShareClient.from_connection_string(conn_str=connection_string, share_name=my_share) root_dir_client = share_client.get_directory_client('') # 创建唯一临时目录,with块结束后自动清理所有内容 with tempfile.TemporaryDirectory() as temp_dir: zip_filename = 'zipped_share.zip' zip_path = os.path.join(temp_dir, zip_filename) with ZipFile(zip_path, 'w') as zipf: # 遍历根目录条目,仅处理文件 for item in root_dir_client.list_directories_and_files(): if not item.is_directory: file_name = item.name local_file_path = os.path.join(temp_dir, file_name) file_client = share_client.get_file_client(file_name) # 下载Azure文件到本地临时文件 with open(local_file_path, 'wb') as local_file: file_client.download_file().readinto(local_file) # 将本地文件加入zip包,保留原文件名 zipf.write(local_file_path, file_name) # 返回zip文件响应,指定下载文件名 return send_file(zip_path, as_attachment=True, download_name=zip_filename)
关键优化点
- 用
tempfile.TemporaryDirectory()替代手动创建临时目录:自动生成唯一路径,with块结束后自动删除所有文件,彻底解决文件提前删除和并发冲突问题。 - 增加目录过滤逻辑:通过
item.is_directory判断,仅处理文件条目,避免目录处理报错。 - 明确
download_name参数:指定前端下载时的文件名,避免浏览器识别异常。 - 简化资源清理逻辑:无需手动调用
shutil.rmtree,临时目录的生命周期由上下文管理器自动管理。
内容的提问来源于stack exchange,提问作者tiger t
相关产品推荐
相关产品推荐

