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

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)

关键优化点

  1. 无磁盘写入:全程在内存缓冲区处理ZIP片段,直接流式发送给客户端,避免磁盘IO损耗。
  2. 低内存占用:每个文件仅以64KB为单位读取,ZIP缓冲区同样按64KB分片,内存占用稳定在百KB级别。
  3. 高效压缩选择:图片本身已压缩,使用ZIP_STORED无压缩模式可大幅降低CPU负载,提升处理速度;若需压缩其他类型文件,可切换为ZIP_DEFLATED。
  4. 异常容错:添加文件读取异常处理,避免单个文件错误导致整个ZIP生成失败。

环境适配

该方案完全兼容Ubuntu 20.04、Python3及任意版本的Flask,无需额外安装依赖,zipfile为Python标准库,Flask可通过pip install flask安装。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 17:25:31