Потоковое скачивание больших zip-файлов

Zipfile image

Задача: отдавать набор файлов с диска одним zip-архивом без потребления памяти

Как ни странно, стандартных утилит python и django для этого оказалось недостаточно. Если вкрадце - для этого написана отдельная либа, на основе стандартного модуля zipfile, которая решает эту проблему. Как-то так:

# views.py
from pathlib import Path

from django.http import StreamingHttpResponse
from zipstream import ZipFile, ZIP_DEFLATED


def some_streaming_zipfile_view(request):
    """A view that streams a large zip-file."""
    zip_stream = ZipFile(mode='w', compression=ZIP_DEFLATED)
    for file_path in Path.home().glob('**/*'):
        zip_stream.write(str(file_path))

    response = StreamingHttpResponse(zip_stream, content_type="application/zip")
    response['Content-Disposition'] = 'attachment; filename="home.zip"'
    return response

Первые три строки функции some_streaming_zipfile_view, сохраняют имена всех файлов из домашней директории пользователя. А процедура сжатия начинается уже после выхода из функции: когда StreamingHttpResponse начинает передавать HTTP-body пользователю итерируя zip_stream.

Так-же есть форк этой либы, который решает некоторые баги.

Но, зачем?

Решаем две проблемы:

  • Не потребляем дополнительного места на диске и в оперативной памяти

  • Не ждём сжатия, а начинаем отдавать zip-файл сразу.
    Избегаем разрывов по таймауту в продакшене на nginx.

Алтернативы

Если в качестве реверс-проки выбран nginx, можно воспользоваться его модуем mod_zip и django_zip_stream.

К сожалению, больше ничего путного я не нашёл. В том, числе для аналогичной работы c tarfile.

Комментарии


Комментариев пока не было

Добавить комментарий

Можете воспользоваться разметкой Markdown.

Лента комментариев

Контакты