1. FastDFS的Python客户端
python版本的FastDFS客户端使用说明参考https://github.com/jefforeilly/fdfs_client-py
后面我们需要用到此链接中的如下图代码:
注意:记得把tracker和storage先运行起来哦~~~~
安装
安装fdfs_client-py-master.zip,文件下载链接地址:https://files.cnblogs.com/files/cl-python/fdfs_client-py-master.zip到虚拟环境中,将文件复制到ubuntu桌面,cd到桌面,终端workon进入到django的虚拟环境中,执行以下命令:
pip install fdfs_client-py-master.zip
pip install mutagen
pip install requests
使用
使用FastDFS客户端,需要有配置文件。我们在meiduo_mall/utils目录下新建fastdfs目录,将client.conf配置文件放到这个目录中。
需要修改一下client.conf配置文件
base_path=/home/python/Desktop #FastDFS客户端存放日志文件的目录
tracker_server=运行tracker服务的机器ip:22122
上传文件需要先创建fdfs_client.client.Fdfs_client的对象,并指明配置文件,如
from fdfs_client.client import Fdfs_client
client=Fdfs_client("meiduo_mall/utils/fastdfs/client.conf")
通过创建的客户端对象执行上传文件的方法
client.upload_by_filename(文件名) 或 client.upload_by_buffer(文件bytes数据)
如下图:
- Remote file_id 即为FastDFS保存的文件的路径
2. 自定义Django文件存储系统
Django自带文件存储系统,但是默认文件存储在本地,在本项目中,我们需要将文件保存到FastDFS服务器上,所以需要自定义文件存储系统。
自定义Storage 参考网址:https://segmentfault.com/a/1190000003708436
from django.core.files.storage import Storage from fdfs_client.client import Fdfs_client from django.conf import settings class FastDFSStorage(Storage): """自定义文件存储系统:实现文件被转存到fdfs""" def __init__(self, client_conf=None, base_url=None): """构造方法 当在存储数据时,django会自动的调用构造方法,"但不会传参进来" """ self.client_conf = client_conf or settings.FDFS_CLIENT_CONF self.base_url = base_url or settings.FDFS_BASE_URL def _open(name, mode='rb'): """打开文件时调用的 因为此时只有文件的上传,没有文件要打开,但是了又必须实现,所以pass """ pass def _save(self, name, content): """ 存储文件时调用的 :param name: 要存储的文件的名字 :param content: 要存储的文件的对象,File类型的对象,需要调用read()读取出要上传的文件的内容 :return: file_id """ # 创建fdfs客户端,跟tracker进行交互 # 'meiduo_mall/utils/fastdfs/client.conf' client = Fdfs_client(self.client_conf) # 调用上传方法:根据文件的内容上传的 为什么不用client.upload_by_filename()?因为不知道 #文件的路径,只知道上传的内容 ret = client.upload_by_buffer(content.read()) # 判断上传是否成功 if ret.get('Status') != 'Upload successed.': raise Exception('upload file failed') # 返回file_id: 模型类会自动的读取这个file_id,存储到模型类中image的ImageField字段 file_id = ret.get('Remote file_id') return file_id def exists(self, name): """ 判断文件是否已经在本地存储, 返回True表示文件已经存储在本地,django不会再去存储该文件 返回False时,告诉Django该文件是新的文件,请你存储。只有返回False,Django才会积极的存储文件到fdfs :param name: 要上传的文件的名字 :return: False """ return False def url(self, name): """ 返回文件的全路径 该方法是提供给模型类中的ImageField字段对应的属性调用的(file_id被存储在ImageField字段中) :param name: 要返回全路径的文件的名字 :return: http://192.168.103.132:8888/group1/M00/00/02/wKhnhFsyPH-AaOwQAAC4j90Tziw46.jpeg """ # 'http://192.168.103.132:8888/' return self.base_url + name
说明:
存储类中必须实现_open()
和_save()
方法,以及任何后续使用中可能用到的其他方法。
-
_open(name, mode='rb')
被Storage.open()调用,在打开文件时被使用。
-
_save(name, content)
被Storage.save()调用,name是传入的文件名,content是Django接收到的文件内容,该方法需要将content文件内容保存。
Django会将该方法的返回值保存到数据库中对应的文件字段,也就是说该方法应该返回要保存在数据库中的文件名称信息。
-
exists(name)
如果名为name的文件在文件系统中存在,则返回True,否则返回False。
-
url(name)
返回文件的完整访问URL
-
delete(name)
删除name的文件
-
listdir(path)
列出指定路径的内容
-
size(name)
返回name文件的总大小
注意,并不是这些方法全部都要实现,可以省略用不到的方法。
在settings.py文件中添加配置:
# django文件存储 DEFAULT_FILE_STORAGE = 'meiduo_mall.utils.fastdfs.fdfs_storage.FastDFSStorage' # FastDFS FDFS_BASE_URL = 'http://192.168.xxx.xxx:8888/' FDFS_CLIENT_CONF = os.path.join(BASE_DIR, 'utils/fastdfs/client.conf')