示例#1
0
 def download(self, name):
     cli = Fdfs_client(self.conf_path)
     if not isinstance(name, bytes):
         name = name.encode()
     try:
         result = cli.download_to_buffer(name)
     except FDFSError as e:
         raise errors.Error(errmsg=f'从FastDFS下载文件{name}失败:') from e
     # logger.debug(f'FastDFS download: {result}')
     content = result.get('Content')
     # remote_file_id = result.get('Remote file_id')
     # storage_ip = result.get('Storage IP')
     # size = result.get('Download size')
     return aes_decrypt(content, key=CONFIG.FILE_SECRET, a2b=False)
示例#2
0
class Fdfs():
    def __init__(self, client_file):
        self.client = Fdfs_client(client_file)

    def upload(self, upload_file):
        try:
            ret_upload = self.client.upload_by_filename(upload_file)
            file_id = ret_upload['Remote file_id'].replace('\\', '/')
            return file_id

        except Exception as e:
            return None

    def uploadbyBuffer(self, file, suffix):
        try:
            ret_upload = self.client.upload_by_buffer(file, suffix)
            file_id = ret_upload['Remote file_id'].replace('\\', '/')
            return file_id
        except Exception as e:
            print(e)
            return None

    def downloadbyBuffer(self, file_id):
        try:
            ret_download = self.client.download_to_buffer(file_id)
            ret_content = ret_download['Content']
            return ret_content
        except Exception as e:
            return None

    def download(self, download_file, file_id):
        try:
            ret_download = self.client.download_to_file(download_file, file_id)
            ret_content = ret_download['Content']
            return ret_content
        except Exception as e:
            return None

    def delete(self, file_id):
        try:
            ret_delete = self.client.delete_file(file_id)
            return ret_delete
        except Exception as e:
            return None
示例#3
0
class FastDfsStorage(Storage):
    """操作文件通过file_id"""

    def __init__(self, base_url=None, client_conf=None):
        """
        初始化
        :param base_url:构造图片上传的基本url,包括域名,已经搭配nginx
        :param client_conf:FastDfs客户端的配置字典
        """
        if base_url is None:
            base_url = FDFS_URL
        self.base_url = base_url
        if client_conf is None:
            client_conf = FDFS_CLIENT_CONF
        self.client_conf = client_conf
        self.client = Fdfs_client(get_tracker_conf(self.client_conf))

    def _open(self, name, mode='rb'):
        """返回封装后的文件对象"""
        return File(open(self.path(name), mode))

    def open(self, name, mode='rb'):
        """
        从FastDfs中取出文件
        :param name: 文件名
        :param mode: 打开的模式
        :return:
        """
        return self._open(name, mode)

    def _save(self, name, content):
        """
        存储文件到FastDfs上
        :param name:  文件名(无卵用)
        :param content: 打开的file对象
        :return:
        """
        filebuffer = content.read()  # 读取二进制内容
        is_save, ret_upload = self.upload(filebuffer)
        return ret_upload.get('Remote file_id').decode() if is_save else None

    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.
        # 要不要name无所谓,只是为了尽量不改底层源码
        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 update(self, filebuffer, remote_file_id):
        """
        修改文件内容
        :param local_path: 本地文件名
        :param remote_file_id:  fastdfs中的file_id
        @return: dictionary {
            'Status'     : 'Modify successed.',
            'Storage IP' : storage_ip
        }
        """

        try:
            remote_file_id = bytes(remote_file_id.encode("utf-8"))  # 旧的file_id
            ret_update = self.client.modify_by_buffer(filebuffer, remote_file_id)
            if ret_update.get("Status") != 'Modify successed.':
                raise Exception
            return True, ret_update
        except Exception as e:
            common_logger.info(e)
            return None, "文件更新失败"

    def upload(self, filebuffer, meta_dict=None):
        """
        保存文件时回调的函数
        保存在FastDfs中
        通过client来操作
        :param name: 文件名
        :param filebuffer: 文件内容(二进制)
        :param meta_dict: dictionary e.g.:{
            'ext_name'  : 'jpg',
            'file_size' : '10240B',
            'width'     : '160px',
            'hight'     : '80px'
        }
        @return dict {
            '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 success else None
        """
        try:
            ret_upload = self.client.upload_by_buffer(filebuffer)
            if ret_upload.get("Status") != "Upload successed.":
                raise Exception
            return True, ret_upload
            # file_name为bytes类型,只能返回str类型,不然会报错
        except Exception as e:
            return False, None

    def url(self, name):
        """
        返回文件的完整URL路径给前端
        :param name: 数据库中保存的文件名
        :return: 完整的URL
        """
        return self.base_url + '/' + name

    def exists(self, name):
        """
        判断文件是否存在,FastDFS可以自行解决文件的重名问题
        所以此处返回False,告诉Django上传的都是新文件
        :param name:  文件名
        :return: False
        """
        return False

    def download_to_file(self, local_path, remote_file_id):
        """
        从FastDfs分布式文件系统进行下载文件,保存成文件格式
        :param local_path: 本地保存文件路径
        :param remote_file_id: 上传到FastDfs文件系统中自动生成的文件路径即文件id,
        :return True/False, dict {
            'Remote file_id'  : remote_file_id,
            'Content'         : local_filename,
            'Download size'   : downloaded_size,
            'Storage IP'      : storage_ip
        }
        """
        try:
            ret_download = self.client.download_to_file(local_path, remote_file_id)
            return True, ret_download
        except Exception as e:
            return False, None

    def download_to_buffer(self, remote_file_id, offset=0, down_bytes=0):
        """
        通过文件名从FastDfs上下载文件,存储为buffer格式
        :param local_filename: 本地文件名,一般存于数据库
        :param remote_file_id: 远程文件id
        :param offset: 文件数据起始偏移量
        :param down_bytes: 需要下载的文件大小
        :return:return True/False, dict {
            'Remote file_id'  : remote_file_id,
            'Content'         : file_buffer,
            'Download size'   : downloaded_size,
            'Storage IP'      : storage_ip
        }
        """
        try:
            ret_download = self.client.download_to_buffer(remote_file_id, offset, down_bytes)
            return True, ret_download
        except Exception as e:
            return False, None


    def modify_by_buffer(self, filebuffer, appender_fileid, offset=0):
        """
        通过buffer修改文件内容
        :param filebuffer:文件buffer
        :param appender_fileid:远程文件id
        :param offset:起始偏移量
        :return:True/False, dictionary {
            'Status'     : 'Modify successed.',
            'Storage IP' : storage_ip
        }
        """

        try:
            ret_modify = self.client.modify_by_buffer(filebuffer, appender_fileid, offset)
            return True, ret_modify
        except Exception as e:
            return False, None

    def delete(self, remote_file_id):
        """
        从FastDfs分布式文件系统中将文件删除
        :param remote_file_id: 上传到FastDfs文件系统中自动生成的文件路径即文件id
        @return True/False, tuple ('Delete file successed.', remote_file_id, storage_ip)
        """
        try:
            ret_delete = self.client.delete_file(remote_file_id)
            return True, ret_delete
        except Exception as e:
            return False, None