juliomalegria / django-chunked-upload

Upload large files to Django in multiple chunks, with the ability to resume if the upload is interrupted.
MIT No Attribution
214 stars 71 forks source link

HELP: Integration with django-storages (sftp or ftp) #62

Closed eduramofo closed 3 years ago

eduramofo commented 3 years ago

Hello I'm trying to work an integration using django-storages (sftp or ftp), but it is not working.

Can someone help me, please?

When I work using django.core.files.storage.FileSystemStorage it works normally.

Should it work using django-storages (sftp)? Or not?

Thanks.

class AbstractChunkedUpload(models.Model):
    def append_chunk(self, chunk, chunk_size=None, save=True):
        self.file.close()
        with open(self.file.path, mode='ab') as file_obj:  # mode = append+binary
            file_obj.write(chunk.read())  # We can use .read() safely because chunk is already in memory

        if chunk_size is not None:
            self.offset += chunk_size
        elif hasattr(chunk, 'size'):
            self.offset += chunk.size
        else:
            self.offset = self.file.size
        self._md5 = None  # Clear cached md5
        if save:
            self.save()
        self.file.close()  # Flush

api_1 | This backend doesn't support absolute paths. Traceback (most recent call last): api_1 | File "/usr/share/scapole/upload/models.py", line 12, in append_chunk api_1 | print(self.file.path) api_1 | File "/home/scapole/.local/lib/python3.9/site-packages/django/db/models/fields/files.py", line 57, in path api_1 | return self.storage.path(self.name) api_1 | File "/home/scapole/.local/lib/python3.9/site-packages/django/core/files/storage.py", line 116, in path api_1 | raise NotImplementedError("This backend doesn't support absolute paths.") api_1 | NotImplementedError: This backend doesn't support absolute paths.

eduramofo commented 3 years ago
from chunked_upload.models import ChunkedUpload
# 'ChunkedUpload' class provides almost everything for you.
# if you need to tweak it little further, create a model class
# by inheriting "chunked_upload.models.AbstractChunkedUpload" class

from scapoleaffiliate.storage_backends_sftp import ProductionFilesSSHStorage

SFS = ProductionFilesSSHStorage()

class MyChunkedUpload(ChunkedUpload):
    def append_chunk(self, chunk, chunk_size=None, save=True):
        self.file.close()
        # We can use .read() safely because chunk is already in memory
        chunk_read = chunk.read()
        # mode = append+binary
        SFS.save_custom(self.file.name, chunk_read)
        if chunk_size is not None:
            self.offset += chunk_size
        elif hasattr(chunk, 'size'):
            self.offset += chunk.size
        else:
            self.offset = self.file.size
        self._md5 = None  # Clear cached md5
        if save:
            self.save()
        self.file.close()  # Flush
eduramofo commented 3 years ago
from chunked_upload.models import ChunkedUpload
# 'ChunkedUpload' class provides almost everything for you.
# if you need to tweak it little further, create a model class
# by inheriting "chunked_upload.models.AbstractChunkedUpload" class

from scapoleaffiliate.storage_backends_sftp import ProductionFilesSSHStorage

SFS = ProductionFilesSSHStorage()

class MyChunkedUpload(ChunkedUpload):
    def append_chunk(self, chunk, chunk_size=None, save=True):
        self.file.close()
        # We can use .read() safely because chunk is already in memory
        chunk_read = chunk.read()
        # mode = append+binary
        SFS.save_custom(self.file.name, chunk_read)
        if chunk_size is not None:
            self.offset += chunk_size
        elif hasattr(chunk, 'size'):
            self.offset += chunk.size
        else:
            self.offset = self.file.size
        self._md5 = None  # Clear cached md5
        if save:
            self.save()
        self.file.close()  # Flush
import posixpath
from storages.backends.sftpstorage import SFTPStorage

class ProductionFilesSSHStorage(SFTPStorage):
    def save_custom(self, name, content):
        """Save file via SFTP."""
        path = self._remote_path(name)
        dirname = posixpath.dirname(path)
        if not self.exists(dirname):
            self._mkdir(dirname)
        f = self.sftp.open(path, 'ab')
        f.write(content)
        f.close()
        # set file permissions if configured
        if self._file_mode is not None:
            self.sftp.chmod(path, self._file_mode)
        if self._uid or self._gid:
            self._chown(path, uid=self._uid, gid=self._gid)
        return name