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里是吧)