我正在尝试在Django中压缩一些大文件并将它们作为zipfile流式传输到客户端。问题是它倾向于首先在内存中创建zipfile,然后再发送。这会导致内存耗尽并使Django崩溃。由于存储空间有限,事先将zipfile写入磁盘也不可行。
我使用zipfly包成功实现了这一点,并且在WSGI同步运行Django时工作正常。但是,我需要实现WebSockets并且必须使Django在ASGI异步运行,而流式传输的zipfly实现就出现了问题。
因此,我开始编写自己的实现,并且几乎让它工作了,但仍存在问题。它目前正在尝试即时创建zip文件,但仍在使用相当多的内存。此外,我的代码没有向客户端发送数据流已结束的指示,导致浏览器最终中止传输。
有人能帮助我吗?以下是代码:
async def create_zip_streaming_response(files_to_compress: list, filename: str):
# Create a generator function to yield chunks of data
async def generate():
# Create an in-memory byte buffer to store the compressed data
buffer = BytesIO()
# Create a zip file object
with zipfile.ZipFile(buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
# Iterate over the files and add them to the zip file
for file_path in files_to_compress:
# Get the file name from the file path
file_name = os.path.basename(file_path)
# Add the file to the zip file
zip_file.write(file_path, file_name)
# Flush the buffer to ensure data is written
buffer.flush()
# Move the buffer's read position to the beginning
buffer.seek(0)
# Read the data from the buffer
data = buffer.read()
# Yield the generated data in chunks
yield data
# Reset the buffer for the next file
buffer.truncate(0)
# Create a streaming response using the generator function
response = StreamingHttpResponse(generate(), content_type='application/zip')
response['Content-Disposition'] = f'attachment; filename="{filename}"'
return response
我非常感谢您的帮助。这是一个非常重要的业余项目,我不知道该如何解决这个问题。该项目已经在 Docker 中部署,并且在生产环境中与 Nginx 和 Uvicorn 结合使用。