django与FDFS交互

备注:

参考django官方文档:https://docs.djangoproject.com/zh-hans/3.0/howto/custom-file-storage/

参考博客:https://www.cnblogs.com/jrri/p/11570089.html

1、安装操作FDFS的客户端模块:

pip install py3Fdfs

2、编写自定义的文件存储类:

from django.core.files.storage import Storage
from fdfs_client.client import Fdfs_client,get_tracker_conf

class FDFSStorage(Storage):
    """自定义文件存储类"""
    def _open(self,name):
        pass

    def _save(self,name,content):
        """
        :param name: 选择上传文件的名字
        :param content: 包含上传文件内容的file对象
        :return:
        """
        #创建一个Fdfs_clinet对象
        tracker_path = get_tracker_conf('./utils/client.conf')
        client = Fdfs_client(tracker_path)
        ret = client.upload_by_buffer(content.read())
        # ret = {
        #     'Group name': group_name,
        #     'Remote file_id': remote_file_id,
        #     'Status': 'Upload successed.',
        #     'Local file name': '',
        #     'Uploaded size': upload_size,
        #     'Storage IP': storage_ip
        # }
        if ret.get('Status') != 'Upload successed.':
            raise Exception('上传文件到fast dfs失败!')

        filename = ret.get('Remote file_id')
        return filename.decode()

    def exists(self, name):
        return False

    def url(self, name):
        return name

注意:

(1)、根据django官方文档,_open(self,name)、_save(self,name,content)方法是必须要有的;

(2)、需要将Remote file_id值解码,否则会报错如下:

__str__ returned non-string (type bytes)

(3)、exists和url方法也要加上,否则会报错

(4)、client.conf中配置的tracker的地址要用外网、且阿里云安全组中要开放如下端口(因为fdfs系统是部署到阿里云上的,如果是在同一网段,应该不用这一步操作):

 

 

3、在项目settings.py中加上如下配置:

DEFAULT_FILE_STORAGE = 'utils.fdfs.FDFSStorage'

 

 4、将fdfs中client.conf配置文件拷贝到对应路径下:

 

 5、优化代码:

将client.conf的路径通过配置文件读取;

url函数中返回值拼接上nginx访问的ip、port,便于通过数据库中文件字段.url直接访问该文件

优化后的代码如下:

from django.core.files.storage import Storage
from fdfs_client.client import Fdfs_client,get_tracker_conf

from django.conf import settings

class FDFSStorage(Storage):
    """自定义文件存储类"""
    def _open(self,name):
        pass

    def _save(self,name,content):
        """
        :param name: 选择上传文件的名字
        :param content: 包含上传文件内容的file对象
        :return:
        """
        #创建一个Fdfs_clinet对象
        tracker_path = get_tracker_conf(settings.FDFS_CLIENT_CONFIG)
        client = Fdfs_client(tracker_path)
        ret = client.upload_by_buffer(content.read())
        # ret = {
        #     'Group name': group_name,
        #     'Remote file_id': remote_file_id,
        #     'Status': 'Upload successed.',
        #     'Local file name': '',
        #     'Uploaded size': upload_size,
        #     'Storage IP': storage_ip
        # }
        if ret.get('Status') != 'Upload successed.':
            raise Exception('上传文件到fast dfs失败!')

        filename = ret.get('Remote file_id')
        return filename.decode()

    def exists(self, name):
        return False

    def url(self, name):
        return settings.NGINX_URL + name

 

 6、最终效果

在admin后台上传图片后,存储在数据库中的内容为文件id:

 

 如果更改_save函数的返回值,则数据库中存储的内容也跟着变化,可见该函数返回值的作用是控制上传成功后保存在数据库中的内容:

 

posted @ 2020-06-08 22:55  沧海1024  阅读(359)  评论(0编辑  收藏  举报