Flask流式创建超内存大目录ZIP文件的实现方案咨询
Flask流式生成大目录ZIP(无磁盘写入、低内存占用)
针对你的需求,直接通过流式生成ZIP并实时响应客户端的方案可以解决大目录内存溢出问题,全程无需将ZIP写入磁盘,仅保留小部分缓冲区数据。
核心思路
利用Python标准库zipfile的文件对象接口,配合Flask的StreamingResponse,将ZIP的生成过程拆分为多个数据块,逐块发送给客户端。每个文件处理时仅读取固定大小的片段,避免加载整个大文件到内存。
实现代码
from flask import Flask, StreamingResponse import zipfile import os app = Flask(__name__) class ZipStreamer: """自定义流对象,接收zipfile的写入并分片输出""" def __init__(self, chunk_size=65536): self.buffer = b'' self.chunk_size = chunk_size # 64KB分片,可按需调整 self.output_queue = [] def write(self, data): self.buffer += data # 当缓冲区达到分片大小,拆分并加入输出队列 while len(self.buffer) >= self.chunk_size: chunk = self.buffer[:self.chunk_size] self.buffer = self.buffer[self.chunk_size:] self.output_queue.append(chunk) def flush(self): # 输出剩余的缓冲区数据 if self.buffer: self.output_queue.append(self.buffer) self.buffer = b'' def __iter__(self): # 迭代输出队列中的所有数据块 while self.output_queue: yield self.output_queue.pop(0) def generate_streaming_zip(target_dir): streamer = ZipStreamer() # 使用无压缩模式(ZIP_STORED)处理图片更高效,若需压缩可换ZIP_DEFLATED with zipfile.ZipFile(streamer, mode='w', compression=zipfile.ZIP_STORED) as zip_file: # 遍历目标目录下的所有文件 for root, _, files in os.walk(target_dir): for filename in files: file_path = os.path.join(root, filename) # 计算ZIP内的相对路径,保持目录结构 arcname = os.path.relpath(file_path, target_dir) try: # 逐块读取源文件并写入ZIP with zip_file.open(arcname, 'w') as zip_entry: with open(file_path, 'rb') as source_file: while chunk := source_file.read(streamer.chunk_size): zip_entry.write(chunk) except Exception as e: # 处理文件读取错误,可根据需求记录日志或跳过 print(f"跳过文件 {file_path}: {str(e)}") continue # 输出最后剩余的ZIP数据 streamer.flush() yield from streamer @app.route('/download-large-zip') def download_large_zip(): # 替换为你的目标大目录路径 target_directory = "/mnt/2tb-storage/large-image-dir" response = StreamingResponse( generate_streaming_zip(target_directory), mimetype="application/zip" ) # 设置下载文件名 response.headers["Content-Disposition"] = "attachment; filename=large_images.zip" return response if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
关键优化点
- 无磁盘写入:全程在内存缓冲区处理ZIP片段,直接流式发送给客户端,避免磁盘IO损耗。
- 低内存占用:每个文件仅以64KB为单位读取,ZIP缓冲区同样按64KB分片,内存占用稳定在百KB级别。
- 高效压缩选择:图片本身已压缩,使用
ZIP_STORED无压缩模式可大幅降低CPU负载,提升处理速度;若需压缩其他类型文件,可切换为ZIP_DEFLATED。 - 异常容错:添加文件读取异常处理,避免单个文件错误导致整个ZIP生成失败。
环境适配
该方案完全兼容Ubuntu 20.04、Python3及任意版本的Flask,无需额外安装依赖,zipfile为Python标准库,Flask可通过pip install flask安装。
内容的提问来源于stack exchange,提问作者James Watson
相关产品推荐
相关产品推荐

