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

浙公网安备 33010602011771号