FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡.
<?php //namespace Common\Util; /** * 分布式文件系统类 */ class FastDFS { static $_instance; //单例 private $_fdfs; //FastDFS 类对象 private $tracker_host; //tracker ip_addr private $tracker_port; //tracker port private $group = null; //storage中的组名,可以为空 private $tracker; //type:array 客户端连接跟踪器(tracker)返回的tracker服务端相关信息 private $storage; //type:array 客户端连接存储节点(storage)返回的storage服务端相关信息 private $debug = true; //错误控制false/true /* localfile 本地文件 group 组名 remotefile 、 masterfile 远程文件(服务器上的文件) file_id 、 masterfile_id 文件id : file_id(masterfile_id)= group/remotefile(或masterfile) $prefixname 从文件的标识 file_ext 文件的后缀名,不包含点'.' meta 文件属性列表,可以包含多个键值对 */ /** * 构造方法 */ private function __construct($config) { if (!extension_loaded('fastdfs_client')) { die('系统未安装FastDFS扩展'); } foreach ($config as $key => $val) { $this->$key = $val; } $this->_fdfs = new FastDFS(); $this->tracker = $this->_fdfs->connect_server($this->tracker_host, $this->tracker_port); if (is_array($this->tracker) && $this->group) { $this->storage = $this->_fdfs->tracker_query_storage_store($this->group, $this->tracker); if (!is_array($this->storage)) { $this->halt(); } } else { if (!is_array($this->tracker)) $this->halt(); } } public static function getInstance($config=null) { if(empty($config)){ $config=C('FASTDFS'); } if (!(self::$_instance instanceof self)) { self::$_instance = new self($config); } return self::$_instance; } private function __clone() { } /* * 文件上传* */ /** * 上传文件 * @param (string)$localfile 本地文件(若文件为完整文件名+后缀的形式,$file_ext可以为空) * @param (string)$group 文件组名 * @param (array) $file_ext 文件的后缀名,不包含点'.'(例:'png') * @param (array) $meta 文件的附加信息,数组格式,array('hight'=>'350px'); * @return Array $file_info 返回包含文件组名和文件名的数组,array('group_name'=>'ab','localfile'=>'kajdsf'); */ public function upload_filename($localfile, $group = null, $file_ext = null, $meta = array()) { $bool = $this->check_string($localfile); if (!$bool) return false; $file_info = $this->_fdfs->storage_upload_by_filename($localfile, $file_ext, $meta, $group, $this->tracker); if ($file_info) { return $file_info; } else { $this->halt(); } } /** * 上传文件 * @param (string)$localfile 文件存放位置(若文件为完整文件名+后缀的形式,$file_ext可以为空) * @param (string)$group 文件组名 * @param (array) $file_ext 文件的后缀名,不包含点'.' * @param (array) $meta 文件的附加信息,数组格式,array('hight'=>'350px','author'=>'bobo'); * @return string 返回file_id(文件组名/文件名) */ public function upload_filename1($localfile, $group = null, $file_ext = null, $meta = array()) { $bool = $this->check_string($localfile); if (!$bool) return false; $file_id = $this->_fdfs->storage_upload_by_filename1($localfile, $file_ext, $meta, $group, $this->tracker); if ($file_id) { return $file_id; } else { $this->halt(); } } /** * 上传从文件 * @param (string)$localfile 从文件名 * @param (string)$group 主文件组名 * @param (string)$masterfile 主文件名 * @param (string)$prefixname 从文件的标识符; 例如,主文件为abc.jpg,从文件需要大图,添加'_b',则$prefixname = '_b'; * @param (string)$file_ext 从文件后缀名 * @param (array)$meta 文件的附加信息,数组格式,array('hight'=>'350px','author'=>'bobo'); * @return Array 返回包含文件组名和文件名的数组,array('group_name'=>'ab','localfile'=>'kajdsf'); */ public function upload_slave_filename($localfile, $group, $masterfile, $prefixname, $file_ext = null, $meta = array()) { $bool = $this->check_string($localfile, $group, $masterfile, $prefixname); if (!$bool) return false; if (!$file_ext) $file_ext = null; $file_info = $this->_fdfs->storage_upload_slave_by_filename($localfile, $group, $masterfile, $prefixname, $file_ext, $meta, $this->tracker); if ($file_info) { return $file_info; } else { $this->halt(); } } /** * 上传从文件 * @param (string)$localfile 从文件名 * @param (string)$masterfile_id 主文件file_id * @param (string)$prefixname 从文件的标识符; 例如,主文件为abc.jpg,从文件需要大图,添加'_b',则$prefixname = '_b'; * @param (string)$file_ext 从文件后缀名 * @param (array)$meta 文件的附加信息,数组格式,array('hight'=>'350px','author'=>'bobo'); * @return Array 返回包含文件组名和文件名的数组,array('group_name'=>'ab','localfile'=>'kajdsf'); */ public function upload_slave_filename1($localfile, $masterfile_id, $prefixname, $file_ext = null, $meta = array()) { $bool = $this->check_string($localfile, $masterfile_id, $prefixname); if (!$bool) return false; if (!$file_ext) $file_ext = null; $file_id = $this->_fdfs->storage_upload_slave_by_filename1($localfile, $masterfile_id, $prefixname, $file_ext, $meta, $this->tracker); if ($file_id) { return $file_id; } else { $this->halt(); } } /** * 上传文件,通过文件流的方式(未测试) * @param $filebuff 文件流 * @param (string)$file_ext 文件的后缀名,不包含点'.' * @param (array) $meta 文件的附加信息,数组格式,array('hight'=>'350px','author'=>'bobo'); * @param (string)$group 文件组名 * @return Array 返回包含文件组名和文件名的数组,array('group_name'=>'ab','filename'=>'kajdsf'); */ public function upload_filebuff($filebuff, $file_ext, $group = null, $meta = array()) { $bool = $this->check_string($filebuff, $file_ext); if (!$bool) return false; $file_info = $this->_fdfs->storage_upload_by_filebuff($filebuff, $file_ext, $meta, $group, $this->tracker); if ($file_info) { return $file_info; } else { $this->halt(); } } /** * 上传从文件,通过文件流的方式(未测试) * @param $filebuff 文件流 * @param (string)$file_ext 文件的后缀名,不包含点'.' * @param (array) $meta 文件的附加信息,数组格式,array('hight'=>'350px','author'=>'bobo'); * @param (string)$group 文件组名 * @return Array 返回包含文件组名和文件名的数组,array('group_name'=>'ab','filename'=>'kajdsf'); */ public function upload_slave_filebuff($filebuff, $group, $masterfile, $prefix_name = null, $file_ext = null, $meta = array()) { $bool = $this->check_string($filebuff, $group, $masterfile); if (!$bool) return false; $file_info = $this->_fdfs->storage_upload_slave_by_filebuff($filebuff, $group, $masterfile, $prefix_name, $file_ext, $meta, $this->tracker); if ($file_info) { return $file_info; } else { $this->halt(); } } /* * 文件删除* */ /** * 删除文件 * @param (string)$group 文件组名 * @param (string)$remotefile 文件名 * @param (string)$filename 主文件名(masterfile或file_id 两种形式) * @param (string)$prefixname 扩展后缀名 * @return bool 成功返回true,失败返回false; */ public function delete_filename($group, $remotefile, $prefix = null, $file_ext = null) { $bool = $this->check_string($group, $remotefile); if (!$bool) return false; if ($prefix) { $remotefile = $this->get_slave_filename($remotefile, $prefix, $file_ext); } $bool = $this->_fdfs->storage_delete_file($group, $remotefile, $this->tracker); if ($bool) { return true; } else { $this->halt(); } } /** * 删除文件 * @param (string)masterfile_id 文件id * @param (string)$filename 主文件名(masterfile或file_id 两种形式) * @param (string)$prefixname 扩展后缀名 * @return bool 成功返回true,失败返回false; */ public function delete_filename1($masterfile_id, $prefix = null, $file_ext = null) { $bool = $this->check_string($masterfile_id); if (!$bool) return false; if ($prefix) { $masterfile_id = $this->get_slave_filename($masterfile_id, $prefix, $file_ext); } $bool = $this->_fdfs->storage_delete_file1($masterfile_id, $this->tracker); if ($bool) { return true; } else { $this->halt(); } } /* * 文件下载* */ /** * 下载文件到本地服务器 * @param (string)$group 文件组名 * @param (string)$remotefile 文件名 * @param (string)$localfile 本地文件名 * @param (string)$filename 主文件名(masterfile或file_id 两种形式) * @param (string)$prefixname 扩展后缀名 * @param $file_offset //file start offset, default value is 0 * @param $download_bytes //0 (default value) means from the file offset to the file end * @return bool 成功返回true,失败返回false */ public function download_filename($group, $remotefile, $localfile, $prefix = null, $file_ext = null, $file_offset = 0, $download_bytes = 0) { $bool = $this->check_string($group, $remotefile, $localfile); if (!$bool) return false; if ($prefix) { $remotefile = $this->get_slave_filename($remotefile, $prefix, $file_ext); } $bool = $this->_fdfs->storage_download_file_to_file($group, $remotefile, $localfile, $file_offset, $download_bytes, $this->tracker); if ($bool) { return true; } else { $this->halt(); } } /** * 下载文件到本地服务器 * @param (string)$file_id 文件id * @param (string)$localfile 本地文件名 * @param (string)$filename 主文件名(masterfile或file_id 两种形式) * @param (string)$prefixname 扩展后缀名 * @param $file_offset //file start offset, default value is 0 * @param $download_bytes //0 (default value) means from the file offset to the file end * @return bool 成功返回true,失败返回false */ public function download_filename1($file_id, $localfile, $prefix = null, $file_ext = null, $file_offset = 0, $download_bytes = 0) { $bool = $this->check_string($file_id, $localfile); if (!$bool) return false; if ($prefix) { $file_id = $this->get_slave_filename($file_id, $prefix, $file_ext); } $bool = $this->_fdfs->storage_download_file_to_file1($file_id, $localfile, $file_offset, $download_bytes, $this->tracker); if ($bool) { return true; } else { $this->halt(); } } /** * 下载文件流(未测试) * @param (string)$group 文件组名 * @param (string)$remotefile 文件名 * @param (string)$filename 主文件名(masterfile或file_id 两种形式) * @param (string)$prefixname 扩展后缀名 * @param $file_offset //file start offset, default value is 0 * @param $download_bytes //0 (default value) means from the file offset to the file end * @return 成功返回文件流,失败返回false */ public function download_filebuff($group, $remotefile, $file_offset = 0, $download_bytes = 0) { $bool = $this->check_string($group, $remotefile); if (!$bool) return false; $bool = $this->_fdfs->storage_download_file_to_buff($group, $remotefile, $file_offset, $download_bytes, $this->tracker); if ($bool) { return true; } else { $this->halt(); } } /* * 辅助方法--判断文件是否存在* */ /** * 判断文件是否存在 * @param (string)$remotefile 文件名 * @param (string)$group 文件组名 * @param (string)$filename 主文件名(masterfile或file_id 两种形式) * @param (string)$prefixname 扩展后缀名 * @return Bool */ public function file_exist($group, $remotefile, $prefix = null, $file_ext = null) { $bool = $this->check_string($group, $remotefile); if (!$bool) return false; if ($prefix) { $remotefile = $this->get_slave_filename($remotefile, $prefix, $file_ext); } $bool = $this->_fdfs->storage_file_exist($group, $remotefile, $this->tracker); if ($bool) { return true; } else { $this->halt(); } } /** * 判断文件是否存在 * @param (string)$file_id 文件id * @param (string)$filename 主文件名(masterfile或file_id 两种形式) * @param (string)$prefixname 扩展后缀名 * @return Bool */ public function file_exist1($file_id, $prefix = null, $file_ext = null) { $bool = $this->check_string($file_id); if (!$bool) return false; if ($prefix) { $file_id = $this->get_slave_filename($file_id, $prefix, $file_ext); } $bool = $this->_fdfs->storage_file_exist1($file_id, $this->tracker); if ($bool) { return true; } else { $this->halt(); } } /* * 辅助方法--根扩展后缀获取从文件名* */ /** * 根据扩展后缀获取从文件名(masterfile或file_id 两种形式) * @param (string)$filename 主文件名(masterfile或file_id 两种形式) * @param (string)$prefixname 扩展后缀名 * @param (string)$file_ext 文件后缀名(这个后缀名替换掉原有文件后缀名) * @return string */ public function get_slave_filename($filename, $prefixname, $file_ext = null) { $bool = $this->check_string($filename, $prefixname); if (!$bool) return false; if (!$file_ext) $file_ext = null; $filename = $this->_fdfs->gen_slave_filename($filename, $prefixname, $file_ext); if ($filename) { return $filename; } else { $this->halt(); } } /* * 辅助方法--反解析远程文件名* */ /** * 反解析远程文件名(只解析主文件名) * 通过此方法可以分析文件名的组成 * @param (string)$remotefile 文件名 * @param (string)$group 文件组名 * @return array Array ( [create_timestamp] => 1346085049 [file_size] => 1235 [source_ip_addr] => 192.168.127.6 [crc32] => -52246624 ) */ public function get_file_info($group, $remotefile) { $bool = $this->check_string($group, $remotefile); if (!$bool) return false; $res = $this->_fdfs->get_file_info($group, $remotefile); if ($res) { return $res; } else { $this->halt(); } } /** * 反解析远程文件名(只解析主文件名) * 通过此方法可以分析文件名的组成 * @param (string)$file_id 文件id * @return array Array ( [create_timestamp] => 1346085049 [file_size] => 1235 [source_ip_addr] => 192.168.127.6 [crc32] => -52246624 ) */ public function get_file_info1($file_id) { $bool = $this->check_string($file_id); if (!$bool) return false; $res = $this->_fdfs->get_file_info1($file_id); if ($res) { return $res; } else { $this->halt(); } } /* * 辅助方法--文件meta操作* */ /** * 设置文件meta * @param (string)$remotefile 文件名 * @param (string)$group 文件组名 * @param (array)$metadata meta信息 * @param (string)$filename 主文件名(masterfile或file_id 两种形式) * @param (string)$prefixname 扩展后缀名 * @return bool */ public function set_metadata($group, $remotefile, $metadata, $prefix = null, $file_ext = null) { $bool = $this->check_string($group, $remotefile, $metadata); if (!$bool) return false; if ($prefix) { $remotefile = $this->get_slave_filename($remotefile, $prefix, $file_ext); } $bool = $this->_fdfs->storage_set_metadata($group, $remotefile, $metadata, FDFS_STORAGE_SET_METADATA_FLAG_OVERWRITE, $this->tracker); if ($bool) { return true; } else { $this->halt(); } } /** * 设置文件meta * @param (string)$file_id 文件id * @param (array)$metadata meta信息 * @param (string)$filename 主文件名(masterfile或file_id 两种形式) * @param (string)$prefixname 扩展后缀名 * @return bool */ public function set_metadata1($file_id, $metadata, $prefix = null, $file_ext = null) { $bool = $this->check_string($file_id, $metadata); if (!$bool) return false; if ($prefix) { $file_id = $this->get_slave_filename($file_id, $prefix, $file_ext); } $bool = $this->_fdfs->storage_set_metadata1($file_id, $metadata, FDFS_STORAGE_SET_METADATA_FLAG_MERGE, $this->tracker); if ($bool) { return true; } else { $this->halt(); } } /** * 得到文件meta * @param (string)$remotefile 文件名 * @param (string)$group 文件组名 * @param (string)$filename 主文件名(masterfile或file_id 两种形式) * @param (string)$prefixname 扩展后缀名 * @return array */ public function get_metadata($group, $remotefile, $prefix = null, $file_ext = null) { $bool = $this->check_string($group, $remotefile); if (!$bool) return false; if ($prefix) { $remotefile = $this->get_slave_filename($remotefile, $prefix, $file_ext); } $res = $this->_fdfs->storage_get_metadata($group, $remotefile, $this->tracker); if ($res) { return $res; } else { $this->halt(); } } /** * 得到文件meta * @param (string)$file_id 文件id * @param (string)$filename 主文件名(masterfile或file_id 两种形式) * @param (string)$prefixname 扩展后缀名 * @return array */ public function get_metadata1($file_id, $prefix = null, $file_ext = null) { $bool = $this->check_string($file_id); if (!$bool) return false; if ($prefix) { $file_id = $this->get_slave_filename($file_id, $prefix, $file_ext); } $res = $this->_fdfs->storage_get_metadata1($file_id, $this->tracker); if ($res) { return $res; } else { $this->halt(); } } /* * 辅助方法--获取storage server信息* */ /** * 获取一个$group内的所有server信息 * @param (string)$group 文件组名 * @return array Array ( [0] => Array ( [ip_addr] => 192.168.127.13 [port] => 23000 [sock] => -1 [store_path_index] => 0 ) [1] => Array ( [ip_addr] => 192.168.127.14 [port] => 23000 [sock] => -1 [store_path_index] => 0 ) ) */ public function get_storage_store_list($group) { $bool = $this->check_string($group); if (!$bool) return false; $res = $this->_fdfs->tracker_query_storage_store_list($group, $this->tracker); if ($res) { return $res; } else { $this->halt(); } } /** * 获取一个$group内的所有server的状态信息 * @param (string/null)$group 文件组名 * @return array * @说明 */ public function get_tracker_list_groups($group) { $bool = $this->check_string($group); if (!$bool) return false; $res = $this->_fdfs->tracker_list_groups($group, $this->tracker); if ($res) { return $res; } else { $this->halt(); } } /** * 返回当前操作到$group/$remotefile资源的storage server信息 * @param (string)$remotefile 文件名 * @param (string)$group 文件组名 * @return array Array ( [0] => Array ( [ip_addr] => 192.168.127.6 [port] => 23000 [sock] => -1 ) ) * @说明 一个group内如果存在多台storage,每台都存在'group/remotefile'相同资源,当下载或者获取数据时此方法返回的是正在操作的资源所在的storage service信息 */ public function get_storage_fetch($group, $remotefile) { $bool = $this->check_string($group, $remotefile); if (!$bool) return false; $res = $this->_fdfs->tracker_query_storage_fetch($group, $remotefile, $this->tracker); if ($res) { return $res; } else { $this->halt(); } } /** * 返回当前操作到$group/$remotefile资源的storage server信息 * @param (string)$file_id 文件id * @return array Array ( [0] => Array ( [ip_addr] => 192.168.127.6 [port] => 23000 [sock] => -1 ) ) * @说明 一个group内如果存在多台storage,每台都存在'group/remotefile'相同资源,当下载或者获取数据时此方法返回的是正在操作的资源所在的storage service信息 */ public function get_storage_fetch1($file_id) { $bool = $this->check_string($file_id); if (!$bool) return false; $res = $this->_fdfs->tracker_query_storage_fetch1($file_id, $this->tracker); if ($res) { return $res; } else { $this->halt(); } } /** * 查找有$group/$remotefile资源的所有storage server信息 * @param (string)$remotefile 文件名 * @param (string)$group 文件组名 * @return array Array ( [0] => Array ( [ip_addr] => 192.168.127.6 [port] => 23000 [sock] => -1 ) ) * @说明 一个group内如果存在多台storage,就会返回拥有上述资源的storage 数组信息 */ public function get_storage_list($group, $remotefile) { $bool = $this->check_string($group, $remotefile); if (!$bool) return false; $res = $this->_fdfs->tracker_query_storage_list($group, $remotefile, $this->tracker); if ($res) { return $res; } else { $this->halt(); } } /** * 查找有$file_id资源的所有storage server信息(返回值同上例) * @param (string)$file_id 文件id * @return array Array ( [0] => Array ( [ip_addr] => 192.168.127.6 [port] => 23000 [sock] => -1 ) ) * @说明 一个group内如果存在多台storage,就会返回拥有上述资源的storage 数组信息 */ public function get_storage_list1($file_id) { $bool = $this->check_string($file_id); if (!$bool) return false; $res = $this->_fdfs->tracker_query_storage_list1($file_id, $this->tracker); if ($res) { return $res; } else { $this->halt(); } } /** * 判断是否是有值的字符串 * @param (array)$arr_str * @return bool */ public function check_string() { $arr_str = func_get_args(); foreach ($arr_str as $value) { if (empty($value)) { return false; } } return true; } /** * 错误控制 * */ public function halt($message = null) { if ($this->debug) { //调试模式下优雅输出错误信息 $trace = debug_backtrace(); $trace_string = ''; foreach ($trace as $key => $t) { $trace_string .= '#' . $key . ' ' . $t['file'] . '(' . $t['line'] . ')' . $t['class'] . $t['type'] . $t['function'] . '(' . implode('.', $t['args']) . ')<br class="last">'; } $errorinfo = $this->_fdfs->get_last_error_info(); echo $errorinfo . '' . $trace_string; exit; } return false; } /** * 析构方法 * 在对象被销毁前调用这个方法,对象属性所占用的内存并销毁对象相关的资源 */ public function __destruct() { if (is_array($this->tracker)) { $this->_fdfs->disconnect_server($this->tracker); } } } //通过调用getInstance()方法,$db现在存有内部存储实例的引用,通过这个实例你可以调用单例类中定义的任何非静态方法 //$config['fastdfs'] = array( // 'tracker_host' => '192.168.1.11', // 默认的FastDFS的地址 // 'tracker_port' => '22122', // 默认的FastDFS的端口 // 'group' => ''// 默认的FastDFS的组名(group1/group2) //); // //$fastdfs = fdfs::getInstance($config['fastdfs']); // //$group = $fastdfs->get_tracker_list_groups('group1'); //print_r($group); //exit;
关键字词: