Django生成Zip文件后下载返回空/非压缩文件问题求助
问题分析与解决方案
核心问题点
- 代码将Zip文件写入服务器磁盘而非内存流,返回的是已关闭的
ZipFile对象而非实际文件内容,导致HttpResponse无法返回有效数据。 Content-Disposition头部拼写错误(attachement应为attachment),浏览器无法正确识别下载类型。- 文件名处理错误,直接使用
ZipFile对象的字符串表示作为文件名,而非预期的合法文件名。 - 手动关闭
ZipFile后返回对象,此时对象已无可用内容。
修正后的代码
1. 内存中构建Zip文件(修改create_downloadable_zip函数)
import io import zipfile def create_downloadable_zip(): container_client = az.container_client(container_name=blob_generator.container_name) blobs = container_client.list_blobs() # 使用BytesIO在内存中创建Zip,避免写入服务器磁盘 zip_buffer = io.BytesIO() # 用with语句自动管理ZipFile资源,无需手动close with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file: for blob in blobs: if blob.name.endswith(".csv"): downloaded_blob = container_client.download_blob(blob) blob_data = downloaded_blob.readall() zip_file.writestr(blob.name, blob_data) # 将文件指针移到缓冲区开头,确保HttpResponse能读取全部内容 zip_buffer.seek(0) # 返回内存流和正确的文件名 return zip_buffer, f'{models.AppRun.client_name}.zip'
2. 修正View函数(修改download_file)
def download_file(request): if request.method == 'POST': zip_buffer, zip_filename = create_downloadable_zip() # 用内存流构建响应,设置正确的Content-Type response = HttpResponse(zip_buffer, content_type='application/zip') # 修正拼写错误,正确设置下载文件名 response['Content-Disposition'] = f'attachment; filename="{zip_filename}"' return response return render(request, "download_file.html")
关键修改说明
- 内存流替代磁盘文件:使用
io.BytesIO在内存中生成Zip,避免服务器磁盘写入,同时直接将内存流传递给HttpResponse。 - 自动资源管理:
with语句会自动关闭ZipFile,避免手动关闭导致的资源问题。 - 重置文件指针:写入Zip内容后,缓冲区指针位于末尾,调用
seek(0)将其移到开头,确保响应能读取完整数据。 - 修正响应头部:修复
Content-Disposition的拼写错误,正确设置下载文件名,让浏览器弹出正确的“另存为”窗口。 - 返回有效数据:不再返回无用的
ZipFile对象,转而返回内存流和文件名,确保View能构建有效下载响应。
内容的提问来源于stack exchange,提问作者Kasper
相关产品推荐
相关产品推荐

