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函数的返回值,则数据库中存储的内容也跟着变化,可见该函数返回值的作用是控制上传成功后保存在数据库中的内容: