Brainstorm's snippets (1/247)

  Automatically zip a FileField upon saving in Django

"""
(c) 2019 Mario Orlandi, Brainstorm S.n.c.

Automatically zip a FileField upon saving in Django

__author__    = "Mario Orlandi"
__copyright__ = "Copyright (c) 2019, Brainstorm S.n.c."
__license__   = "GPL"
"""

import os
import zipfile
from django.core.files.storage import FileSystemStorage


class ZipFileStorage(FileSystemStorage):
    """
    A specialized FileSystemStorage which, upon saving the file,
    transparently compresses it into a zip archive (if not already zipped)

    Sample usage:

        source_data = models.FileField(..., storage=ZipFileStorage())
    """

    def save(self, name, content, max_length=None):

        # Let the base storage class save the file as usual
        name = super().save(name, content, max_length)

        # Check if already zipped
        if not name.lower().endswith('.zip'):

            # If not, create a new zip archive and write the file into it
            path = self.path(name)
            zf = zipfile.ZipFile(path + '.zip', mode='w', compression=zipfile.ZIP_DEFLATED)
            try:
                zf.write(path, os.path.basename(path))
            finally:
                zf.close()

            # Cleanup: the orginal unzipped file can now be removed
            os.remove(path)

            # The new return value will be the name of the zip archive just created
            name += '.zip'

        return name