如何在现代Django中打包单个文件夹内多文件并发送至浏览器
Django 多文件压缩包下载实用方案
核心逻辑
直接在内存中生成压缩包,通过Django响应返回给浏览器,全程不用在服务器创建临时文件,既省磁盘空间又高效。
基础实现代码(适合中小文件)
import io import zipfile from django.http import HttpResponse from django.conf import settings def download_multiple_files_as_zip(request): # 替换成你要压缩的文件路径列表,这里以媒体目录下的文件为例 target_files = [ settings.MEDIA_ROOT / "report.pdf", settings.MEDIA_ROOT / "screenshot.png", settings.MEDIA_ROOT / "data.csv" ] # 初始化内存字节流,用来存压缩包数据 zip_buffer = io.BytesIO() # 创建压缩包,ZIP_DEFLATED是带压缩的模式,要速度的话换ZIP_STORED(无压缩) with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_obj: for file_path in target_files: # 先判断文件存在再添加,避免报错 if file_path.exists(): # arcname是压缩包里显示的文件名,这里用原文件名 zip_obj.write(file_path, arcname=file_path.name) # 把字节流指针移到开头,不然浏览器读不到内容 zip_buffer.seek(0) # 构造响应 response = HttpResponse(zip_buffer, content_type="application/zip") # 指定下载的文件名,浏览器会自动触发下载 response["Content-Disposition"] = 'attachment; filename="download_files.zip"' return response
大文件场景优化
如果要压缩的文件总大小很大,用内存处理容易爆内存,换成流式响应:
import io import zipfile from django.http import StreamingHttpResponse from django.conf import settings def stream_large_files_as_zip(request): target_files = [ settings.MEDIA_ROOT / "big_file1.iso", settings.MEDIA_ROOT / "big_file2.mp4" ] def zip_stream_generator(): with io.BytesIO() as chunk_buffer: with zipfile.ZipFile(chunk_buffer, "w", zipfile.ZIP_DEFLATED) as zip_obj: for file_path in target_files: if file_path.exists(): zip_obj.write(file_path, arcname=file_path.name) # 把当前chunk的内容返回给浏览器 chunk_buffer.seek(0) yield chunk_buffer.read() # 清空buffer准备下一个文件 chunk_buffer.seek(0) chunk_buffer.truncate() response = StreamingHttpResponse(zip_stream_generator(), content_type="application/zip") response["Content-Disposition"] = 'attachment; filename="large_files.zip"' return response
注意点
- 一定要检查文件是否存在,不然会抛出文件不存在的异常
- 内容类型
application/zip必须正确,不然浏览器可能不会识别为压缩包 - 如果是用户上传的文件,要做好权限校验,避免泄露敏感文件
内容的提问来源于stack exchange,提问作者Swantewit
相关产品推荐
相关产品推荐

