from django.conf import settings from django.core.files import File from django.core.files.storage import FileSystemStorage import gzip import os class DjangoGzipFile (File): def chunks( self, chunk_size=None ): if hasattr( self, 'seek' ): self.seek( 0 ) yield self.read() def multiple_chunks( self, chunk_size=None ): return False class GzipFileSystemStorage (FileSystemStorage): nocompress = ('.z','.gz','.zip','.tgz','.jpg','.png','.gif') def should_compress( self, name ): dir_name, file_name = os.path.split( name ) file_root, file_ext = os.path.splitext( file_name ) return file_ext.lower() not in self.nocompress def path( self, name, for_dir=False ): p = super( GzipFileSystemStorage, self ).path( name ) if self.should_compress(name) and not for_dir: p = p + '.gz' return p def _open( self, name, mode='rb' ): if self.should_compress( name ): full_path = self.path( name ) gzip_file = gzip.GzipFile( full_path, mode ) # File._get_size chokes unless self.file has a name attribute. setattr( gzip_file, 'name', full_path ) return DjangoGzipFile( gzip_file ) else: return super( GzipFileSystemStorage, self )._open( name, mode ) def _save( self, name, content ): if not self.should_compress( name ): return super( GzipFileSystemStorage, self )._save( name, content ) full_path = self.path( self.get_available_name(name) ) dir_name, file_name = os.path.split( full_path ) if not os.path.exists( dir_name ): os.makedirs( dir_name ) elif not os.path.isdir( dir_name ): raise IOError( "%s exists and is not a directory." % dir_name ) fd = open( full_path, 'wb' ) gzip_file = gzip.GzipFile( filename=file_name, fileobj=fd, mode='wb' ) for chunk in content.chunks(): gzip_file.write( chunk ) gzip_file.close() fd.close() if settings.FILE_UPLOAD_PERMISSIONS is not None: os.chmod( full_path, settings.FILE_UPLOAD_PERMISSIONS ) return name def listdir( self, path ): path = self.path( path, for_dir=True ) directories, files = [], [] for entry in os.listdir( path ): if os.path.isdir( os.path.join(path,entry) ): directories.append( entry ) else: files.append( entry ) return directories, files