django 自定义fdfs文件存储类

FdfsStorage.py
# -*- coding: utf-8 -*-
import logging
from django.conf import settings
from django.core.files.storage import FileSystemStorage
from fdfs_client.client import Fdfs_client, get_tracker_conf


logger = logging.getLogger('django')


class FdfsStorage(FileSystemStorage):

    def url(self, name):
        """
        全路径
        :param name:
        :return:
        """
        return settings.__getattr__('CUSTOM_STORAGE_BASE_URL') + name

    def save(self, name, content, max_length=None):
        # 现在修好了 直接跳掉原来的保存过程 返回个新name就行 2021.12.10 17:57
        conf = get_tracker_conf(f'{settings.BASE_DIR}/utils/fastdfs/client.conf')
        client = Fdfs_client(conf)
        # res = client.upload_by_buffer(filebuffer=content.file.read())
        res = client.upload_by_buffer(filebuffer=content.file.read(), file_ext_name=name.split('.')[-1])

        new_name = res['Remote file_id'].decode()
        logger.info(f'上传文件至fdfs {res} name:{name} new_name: {new_name}')
        return str(new_name).replace('\\', '/')

  

settings.py 路径随便 找得着就行

UBUNTU1 = '192.168.204.128'

CUSTOM_STORAGE_BASE_URL = f'http://{UBUNTU1}:8888/'  # fdfs

DEFAULT_FILE_STORAGE = 'utils.fastdfs.fdfs_storage.FdfsStorage'

  

 

作为参考 默认的save方法源码如下

def save(self, name, content, max_length=None):
        """
        Save new content to the file specified by name. The content should be
        a proper File object or any Python file-like object, ready to be read
        from the beginning.
        """
        # Get the proper name for the file, as it will actually be saved.
        if name is None:
            name = content.name

        if not hasattr(content, 'chunks'):
            content = File(content, name)

        name = self.get_available_name(name, max_length=max_length)
        return self._save(name, content)

  

def _save(self, name, content):
    full_path = self.path(name)

    # Create any intermediate directories that do not exist.
    directory = os.path.dirname(full_path)
    try:
        if self.directory_permissions_mode is not None:
            # Set the umask because os.makedirs() doesn't apply the "mode"
            # argument to intermediate-level directories.
            old_umask = os.umask(0o777 & ~self.directory_permissions_mode)
            try:
                os.makedirs(directory, self.directory_permissions_mode, exist_ok=True)
            finally:
                os.umask(old_umask)
        else:
            os.makedirs(directory, exist_ok=True)
    except FileExistsError:
        raise FileExistsError('%s exists and is not a directory.' % directory)

    # There's a potential race condition between get_available_name and
    # saving the file; it's possible that two threads might return the
    # same name, at which point all sorts of fun happens. So we need to
    # try to create the file, but if it already exists we have to go back
    # to get_available_name() and try again.

    while True:
        try:
            # This file has a file path that we can move.
            if hasattr(content, 'temporary_file_path'):
                file_move_safe(content.temporary_file_path(), full_path)

            # This is a normal uploadedfile that we can stream.
            else:
                # The current umask value is masked out by os.open!
                fd = os.open(full_path, self.OS_OPEN_FLAGS, 0o666)
                _file = None
                try:
                    locks.lock(fd, locks.LOCK_EX)
                    for chunk in content.chunks():
                        if _file is None:
                            mode = 'wb' if isinstance(chunk, bytes) else 'wt'
                            _file = os.fdopen(fd, mode)
                        _file.write(chunk)
                finally:
                    locks.unlock(fd)
                    if _file is not None:
                        _file.close()
                    else:
                        os.close(fd)
        except FileExistsError:
            # A new name is needed if the file exists.
            name = self.get_available_name(name)
            full_path = self.path(name)
        else:
            # OK, the file save worked. Break out of the loop.
            break

    if self.file_permissions_mode is not None:
        os.chmod(full_path, self.file_permissions_mode)

    # Store filenames with forward slashes, even on Windows.
    return str(name).replace('\\', '/')

  

可以看出 默认的save明显复杂得多 实现了同名/权限等诸多校验

借助Fdfs_client 存储过程用不着自己实现(都在upload_by_buffer里是吧)

上一篇:linux命令收集


下一篇:FastDFS搭建文件管理系统(详细教程),含BATJM大厂