• FastDFS php API


      1 <?php
      2 
      3 if (!class_exists('FastDFS', false)) {
      4     define('FDFS_PROTO_PKG_LEN_SIZE', 8);
      5     define('FDFS_PROTO_CMD_ACTIVE_TEST', 111);
      6     define('FDFS_PROTO_CMD_RESP', 100);
      7     define('FDFS_PROTO_CMD_UPLOAD_SLAVE_FILE', 21);
      8     define('FDFS_PROTO_CMD_DELETE_FILE', 12);
      9     define('FDFS_PROTO_CMD_GET_METADATA', 15);
     10     define('FDFS_PROTO_CMD_SET_METADATA', 13);
     11 
     12     //body_length + command + status
     13     define('FDFS_HEADER_LENGTH', 10);
     14     define('FDFS_IP_ADDRESS_SIZE', 16);
     15     define('FDFS_FILE_EXT_NAME_MAX_LEN', 6);
     16     define('FDFS_GROUP_NAME_MAX_LEN', 16);
     17     define('FDFS_OVERWRITE_METADATA', 1);
     18     define('FDFS_MERGE_METADATA', 2);
     19 
     20     // 连接超时时间
     21     define('FDFS_CONNECT_TIME_OUT', 5);
     22     define('FDFS_FILE_PREFIX_MAX_LEN', 16);
     23 
     24     //传输超时时间
     25     define('FDFS_TRANSFER_TIME_OUT', 0);
     26     define('FDFS_QUERY_STORE_WITHOUT_GROUP_ONE', 101);
     27     define('FDFS_QUERY_STORE_WITH_GROUP_ONE', 104);
     28 
     29     define('FDFS_TRACKER_QUERY_STORAGE_STORE_BODY_LEN', FDFS_GROUP_NAME_MAX_LEN + FDFS_IP_ADDRESS_SIZE + FDFS_PROTO_PKG_LEN_SIZE);
     30 
     31     class FastDFS {
     32 
     33         public $gConfig = array();
     34 
     35         /**
     36          *
     37          * @var FastDFSTrackerClient
     38          */
     39         private $tracker;
     40 
     41         /**
     42          *
     43          * @var FastDFSStorageClient
     44          */
     45         private $storage;
     46         private $error = array(
     47             'code' => 0,
     48             'msg' => ''
     49         );
     50 
     51         /**
     52          * 要使用这个类,你一定要在php的ini文件中进行fastdfs的配置
     53          * 
     54          * @throws FastDFSException
     55          */
     56         public function __construct() {
     57             $configFile = '';
     58             $ini = parse_ini_file(php_ini_loaded_file());
     59 
     60             if (!isset($ini['fastdfs_client.tracker_group_count'])) {
     61                 throw new FastDFSException("no define fastdfs config");
     62             }
     63             for ($i = 0; $i < $ini['fastdfs_client.tracker_group_count']; $i++) {
     64                 if (isset($ini['fastdfs_client.tracker_group' . $i])) {
     65                     $configFile = $ini['fastdfs_client.tracker_group' . $i];
     66                     break;
     67                 }
     68             }
     69             if (!file_exists($configFile)) {
     70                 throw new FastDFSException("client config $configFile not found");
     71             }
     72             $this->gConfig = parse_ini_file($configFile);
     73             list($this->gConfig['tracker_host'], $this->gConfig['tracker_port']) = explode(':', $this->gConfig['tracker_server']);
     74         }
     75 
     76         /**
     77          * 获得一个tracker
     78          * 
     79          * @return FastDFSTrackerClient
     80          */
     81         public function tracker_get_connection() {
     82             $this->tracker = new FastDFSTrackerClient($this, $this->gConfig['tracker_host'], $this->gConfig['tracker_port']);
     83 
     84             return $this->tracker;
     85         }
     86 
     87         /**
     88          * 通过tracker获取一个stroage
     89          * 
     90          * @param string $groupName 文件组名,当为空时,组名由tracker决定
     91          * @param FastDFSTrackerClient $tracker
     92          * @return FastDFSStorageClient
     93          */
     94         public function tracker_query_storage_store($groupName, FastDFSTrackerClient $tracker) {
     95             $this->storage = new FastDFSStorageClient($this, $groupName, $tracker);
     96 
     97             return $this->storage;
     98         }
     99 
    100         /**
    101          * 测试一下tracker服务器是否正常
    102          * 
    103          * @param FastDFSTrackerClient $tracker
    104          * @return boolean
    105          */
    106         public function active_test(FastDFSTrackerClient $tracker = null) {
    107             $this->initTrackerAndStorage($tracker);
    108             
    109             $header = self::packHeader(FDFS_PROTO_CMD_ACTIVE_TEST, 0);
    110             $tracker->send($header);
    111 
    112             $resHeader = self::parseHeader($tracker->read(FDFS_HEADER_LENGTH));
    113 
    114             return $resHeader['status'] == 0 ? true : false;
    115         }
    116 
    117         public function get_last_error_no() {
    118             return $this->error['code'];
    119         }
    120 
    121         public function add_error($errorNo, $info) {
    122             $this->error['code'] = $errorNo;
    123             $this->error['msg'] = $info;
    124         }
    125 
    126         public function get_last_error_info() {
    127             return $this->error['msg'];
    128         }
    129 
    130         /**
    131          * 在storage中删除一个文件
    132          * 
    133          * @param string $groupName 文件所在的组名
    134          * @param string $remoteFile 要删除的文件路径
    135          * @param FastDFSStorageClient $tracker
    136          * @param FastDFSStorageClient $storage
    137          */
    138         public function storage_delete_file($groupName, $remoteFile, FastDFSStorageClient $tracker, FastDFSStorageClient $storage) {
    139             $this->initTrackerAndStorage($tracker, $storage, $groupName);
    140 
    141             $this->storage->deleteFile($groupName, $remoteFile);
    142         }
    143 
    144         /**
    145          * 往storage中上传一个文件
    146          * 
    147          * @param string $localFile 你本地的文件路径
    148          * @param string $extName 文件的扩展名,当名优提供扩展名时,会自动取文件的扩展名
    149          * @param array $metas 文件的附加信息
    150          * @param string $groupName 所在的组名,可以为空,为空时,由tracker决定
    151          * @param FastDFSTrackerClient $tracker
    152          * @param FastDFSStorageClient $storage
    153          */
    154         public function storage_upload_by_filename($localFile, $extName = '', $metas = array(), $groupName = '', FastDFSTrackerClient $tracker = null, FastDFSStorageClient $storage = null) {
    155             $this->initTrackerAndStorage($tracker, $storage, $groupName);
    156 
    157             return $this->storage->uploadByFilename($localFile, $extName, $metas);
    158         }
    159 
    160         /**
    161          * 上传一个文件的附属文件,主要使用一个图片有缩略图的情况下
    162          * 
    163          * @param string $localFile 本地文件的路径,缩略图的文件路径
    164          * @param string $groupName 组名,最好和主文件在同一个组
    165          * @param string $masterFileName 主文件名
    166          * @param string $prefix 文件的前缀
    167          * @param string $extName 文件的后缀,可以为空,为空时,由tracker决定
    168          * @param array $meta 附件信息
    169          * @param FastDFSTrackerClient $tracker
    170          * @param FastDFSStorageClient $storage
    171          */
    172         public function storage_upload_slave_by_filename($localFile, $groupName, $masterFileName, $prefix = '', $extName = '', $meta = array(), FastDFSTrackerClient $tracker = null, FastDFSStorageClient $storage = null) {
    173             $this->initTrackerAndStorage($tracker, $storage, $groupName);
    174             /*echo $localFile."<br/>".$groupName."<br/>".$masterFileName."<br/>".$prefix;
    175             exit;*/
    176             return $this->storage->uploadSalveFile($localFile, $groupName, $masterFileName, $prefix, $extName, $meta);
    177         }
    178 
    179         /**
    180          * 检查这个文件是否已经存在
    181          * 
    182          * @param string $groupName 文件所在组名
    183          * @param string $remoteFile 文件在storage中的名字
    184          * @param FastDFSStorageClient $tracker
    185          * @param FastDFSStorageClient $storage
    186          */
    187         public function storage_file_exist($groupName, $remoteFile, FastDFSTrackerClient $tracker, FastDFSStorageClient $storage) {
    188             $this->initTrackerAndStorage($tracker, $storage, $groupName);
    189 
    190             return $this->storage->fileExists($groupName, $remoteFile);
    191         }
    192 
    193         public function close() {
    194             if ($this->tracker) {
    195                 $this->tracker->close();
    196                 $this->tracker = null;
    197             }
    198         }
    199 
    200         public function tracker_close_all_connections() {
    201             $this->close();
    202             if (!$this->storage) {
    203                 $this->storage->close();
    204             }
    205         }
    206 
    207         public static function padding($str, $len) {
    208 
    209             $str_len = strlen($str);
    210 
    211             return $str_len > $len ? substr($str, 0, $len) : $str . pack('x' . ($len - $str_len));
    212         }
    213 
    214         /**
    215          * 
    216          * @param int $command
    217          * @param int $length
    218          * @return bytes
    219          */
    220         public static function packHeader($command, $length = 0) {
    221             return self::packU64($length) . pack('Cx', $command);
    222         }
    223 
    224         public static function packMetaData($data) {
    225             $S1 = "x01";
    226             $S2 = "x02";
    227 
    228             $list = array();
    229             foreach ($data as $key => $val) {
    230                 $list[] = $key . $S2 . $val;
    231             };
    232 
    233             return implode($S1, $list);
    234         }
    235 
    236         public static function parseMetaData($data) {
    237 
    238             $S1 = "x01";
    239             $S2 = "x02";
    240 
    241             $arr = explode($S1, $data);
    242             $result = array();
    243 
    244             foreach ($arr as $val) {
    245                 list($k, $v) = explode($S2, $val);
    246                 $result[$k] = $v;
    247             }
    248 
    249             return $result;
    250         }
    251 
    252         public static function parseHeader($str, $len = FDFS_HEADER_LENGTH) {
    253 
    254             assert(strlen($str) === $len);
    255 
    256             $result = unpack('C10', $str);
    257 
    258             $length = self::unpackU64(substr($str, 0, 8));
    259             $command = $result[9];
    260             $status = $result[10];
    261 
    262             return array(
    263                 'length' => $length,
    264                 'command' => $command,
    265                 'status' => $status
    266             );
    267         }
    268 
    269         /**
    270          * From: sphinxapi.php
    271          */
    272         private static function unpackU64($v) {
    273             list ( $hi, $lo ) = array_values(unpack("N*N*", $v));
    274 
    275             if (PHP_INT_SIZE >= 8) {
    276                 if ($hi < 0)
    277                     $hi += (1 << 32); // because php 5.2.2 to 5.2.5 is totally fucked up again
    278                 if ($lo < 0)
    279                     $lo += (1 << 32);
    280 
    281                 // x64, int
    282                 if ($hi <= 2147483647)
    283                     return ($hi << 32) + $lo;
    284 
    285                 // x64, bcmath
    286                 if (function_exists("bcmul"))
    287                     return bcadd($lo, bcmul($hi, "4294967296"));
    288 
    289                 // x64, no-bcmath
    290                 $C = 100000;
    291                 $h = ((int) ($hi / $C) << 32) + (int) ($lo / $C);
    292                 $l = (($hi % $C) << 32) + ($lo % $C);
    293                 if ($l > $C) {
    294                     $h += (int) ($l / $C);
    295                     $l = $l % $C;
    296                 }
    297 
    298                 if ($h == 0)
    299                     return $l;
    300                 return sprintf("%d%05d", $h, $l);
    301             }
    302 
    303             // x32, int
    304             if ($hi == 0) {
    305                 if ($lo > 0)
    306                     return $lo;
    307                 return sprintf("%u", $lo);
    308             }
    309 
    310             $hi = sprintf("%u", $hi);
    311             $lo = sprintf("%u", $lo);
    312 
    313             // x32, bcmath
    314             if (function_exists("bcmul"))
    315                 return bcadd($lo, bcmul($hi, "4294967296"));
    316 
    317             // x32, no-bcmath
    318             $hi = (float) $hi;
    319             $lo = (float) $lo;
    320 
    321             $q = floor($hi / 10000000.0);
    322             $r = $hi - $q * 10000000.0;
    323             $m = $lo + $r * 4967296.0;
    324             $mq = floor($m / 10000000.0);
    325             $l = $m - $mq * 10000000.0;
    326             $h = $q * 4294967296.0 + $r * 429.0 + $mq;
    327 
    328             $h = sprintf("%.0f", $h);
    329             $l = sprintf("%07.0f", $l);
    330             if ($h == "0")
    331                 return sprintf("%.0f", (float) $l);
    332             return $h . $l;
    333         }
    334 
    335         private function initTrackerAndStorage(FastDFSTrackerClient $tracker = null, FastDFSStorageClient $storage = null, $groupName = '') {
    336             $reNewStorage = false;
    337             if ($tracker && $tracker !== $this->tracker) {
    338                 $this->tracker_get_connection();
    339             }
    340             if (($storage && $storage !== $this->storage) || $reNewStorage) {
    341                 $this->tracker_query_storage_store($groupName, $this->tracker);
    342             }
    343         }
    344 
    345         /**
    346          * From: sphinxapi.php
    347          */
    348         public static function packU64($v) {
    349 
    350 
    351             assert(is_numeric($v));
    352 
    353             // x64
    354             if (PHP_INT_SIZE >= 8) {
    355                 assert($v >= 0);
    356 
    357                 // x64, int
    358                 if (is_int($v))
    359                     return pack("NN", $v >> 32, $v & 0xFFFFFFFF);
    360 
    361                 // x64, bcmath
    362                 if (function_exists("bcmul")) {
    363                     $h = bcdiv($v, 4294967296, 0);
    364                     $l = bcmod($v, 4294967296);
    365                     return pack("NN", $h, $l);
    366                 }
    367 
    368                 // x64, no-bcmath
    369                 $p = max(0, strlen($v) - 13);
    370                 $lo = (int) substr($v, $p);
    371                 $hi = (int) substr($v, 0, $p);
    372 
    373                 $m = $lo + $hi * 1316134912;
    374                 $l = $m % 4294967296;
    375                 $h = $hi * 2328 + (int) ($m / 4294967296);
    376 
    377                 return pack("NN", $h, $l);
    378             }
    379 
    380             // x32, int
    381             if (is_int($v))
    382                 return pack("NN", 0, $v);
    383 
    384             // x32, bcmath
    385             if (function_exists("bcmul")) {
    386                 $h = bcdiv($v, "4294967296", 0);
    387                 $l = bcmod($v, "4294967296");
    388                 return pack("NN", (float) $h, (float) $l); // conversion to float is intentional; int would lose 31st bit
    389             }
    390 
    391             // x32, no-bcmath
    392             $p = max(0, strlen($v) - 13);
    393             $lo = (float) substr($v, $p);
    394             $hi = (float) substr($v, 0, $p);
    395 
    396             $m = $lo + $hi * 1316134912.0;
    397             $q = floor($m / 4294967296.0);
    398             $l = $m - ($q * 4294967296.0);
    399             $h = $hi * 2328.0 + $q;
    400 
    401             return pack("NN", $h, $l);
    402         }
    403 
    404     }
    405 
    406     abstract class FastDFSBase {
    407 
    408         abstract public function getSocket();
    409 
    410         abstract public function close();
    411 
    412         public function read($length, $socket = null) {
    413             if (!$socket) {
    414                 $socket = $this->getSocket();
    415             }
    416 
    417             if (feof($socket)) {
    418                 throw new FastDFS_Exception('connection unexpectedly closed (timed out?)', $this->_errno);
    419             }
    420 
    421             $data = stream_get_contents($socket, $length);
    422 
    423             assert($length === strlen($data));
    424 
    425             return $data;
    426         }
    427 
    428         public function send($data, $length = 0, $socket = null) {
    429             if (!$socket) {
    430                 $socket = $this->getSocket();
    431             }
    432 
    433             if (!$length) {
    434                 $length = strlen($data);
    435             }
    436 
    437             if (feof($socket) || fwrite($socket, $data, $length) !== $length) {
    438                 throw new Exception('connection unexpectedly closed (timed out?)');
    439             }
    440 
    441             return true;
    442         }
    443 
    444     }
    445 
    446     class FastDFSTrackerClient extends FastDFSBase {
    447 
    448         private $host;
    449         private $port;
    450 
    451         /**
    452          *
    453          * @var FastDFS
    454          */
    455         private $dfs;
    456         private $_socket;
    457 
    458         public function __construct(FastDFS &$dfs, $host, $port) {
    459             $this->host = $host;
    460             $this->port = $port;
    461             $this->dfs = $dfs;
    462 
    463             $this->_socket = @fsockopen("tcp://$host", $port, $errno, $errstr, $this->dfs->gConfig['connect_timeout']);
    464             if (!$this->_socket) {
    465                 $this->dfs->add_error(-2, $errstr);
    466             }
    467         }
    468 
    469         public function getSocket() {
    470             return $this->_socket;
    471         }
    472 
    473         public function close() {
    474             fclose($this->_socket);
    475         }
    476 
    477     }
    478 
    479     class FastDFSStorageClient extends FastDFSBase {
    480 
    481         private $groupName;
    482 
    483         /**
    484          *
    485          * @var FastDFSTrackerClient 
    486          */
    487         private $tracker;
    488 
    489         /**
    490          *
    491          * @var FastDFS
    492          */
    493         private $dfs;
    494         private $_socket;
    495         private $host;
    496         private $port;
    497         private $storeIndex;
    498 
    499         public function __construct(FastDFS &$dfs, $groupName, FastDFSTrackerClient $tracker) {
    500             $this->tracker = $tracker;
    501             $this->dfs = $dfs;
    502 
    503             $reqBody = '';
    504             if ($groupName) {
    505                 $cmd = FDFS_QUERY_STORE_WITH_GROUP_ONE;
    506                 $len = FDFS_GROUP_NAME_MAX_LEN;
    507                 $reqBody = FastDFS::padding($groupName, $len);
    508             } else {
    509                 $cmd = FDFS_QUERY_STORE_WITHOUT_GROUP_ONE;
    510                 $len = 0;
    511             }
    512             $reqHeader = FastDFS::packHeader($cmd, $len);
    513             $this->tracker->send($reqHeader . $reqBody);
    514 
    515             $resHeader = $this->tracker->read(FDFS_HEADER_LENGTH);
    516             $resInfo = FastDFS::parseHeader($resHeader);
    517 
    518             if ($resInfo['status'] != 0) {
    519                 throw new Exception("something wrong with get storage by group name", $resInfo['status']);
    520             }
    521 
    522             $resBody = !!$resInfo['length'] ? $this->tracker->read($resInfo['length']) : '';
    523             $this->groupName = trim(substr($resBody, 0, FDFS_GROUP_NAME_MAX_LEN));
    524             $this->host = trim(substr($resBody, FDFS_GROUP_NAME_MAX_LEN, FDFS_IP_ADDRESS_SIZE + 1));
    525 
    526             list(,, $this->port) = unpack('N2', substr($resBody, FDFS_GROUP_NAME_MAX_LEN + FDFS_IP_ADDRESS_SIZE - 1, FDFS_PROTO_PKG_LEN_SIZE));
    527 
    528             $this->storeIndex = ord(substr($resBody, -1));
    529 
    530             $this->_socket = @fsockopen($this->host, $this->port, $errno, $errstr, $this->dfs->gConfig['connect_timeout']);
    531 
    532             if (!$this->_socket) {
    533                 $this->dfs->add_error($errno, $errstr);
    534             }
    535         }
    536 
    537         public function getSocket() {
    538             return $this->_socket;
    539         }
    540 
    541         public function getStorePathIndex() {
    542             return $this->storeIndex;
    543         }
    544 
    545         public function uploadByFilename($localFile, $extName, $metas) {
    546             if (!file_exists($localFile)) {
    547                 throw new FastDFSException("$localFile file is not exists");
    548             }
    549             $pathInfo = pathinfo($localFile);
    550 
    551             $extName = $extName ? $extName : $pathInfo['extension'];
    552             $extLen = strlen($extName);
    553 
    554             if ($extLen > FDFS_FILE_EXT_NAME_MAX_LEN) {
    555                 throw new FastDFSException("file ext too long");
    556             }
    557             $fp = fopen($localFile, 'rb');
    558             flock($fp, LOCK_SH);
    559             $fileSize = filesize($localFile);
    560 
    561             $reqBodyLen = 1 + FDFS_PROTO_PKG_LEN_SIZE + FDFS_FILE_EXT_NAME_MAX_LEN + $fileSize;
    562             $reqHeader = FastDFS::packHeader(11, $reqBodyLen);
    563             $reqBody = pack('C', $this->getStorePathIndex()) . FastDFS::packU64($fileSize) . FastDFS::padding($extName, FDFS_FILE_EXT_NAME_MAX_LEN);
    564 
    565             $this->send($reqHeader . $reqBody);
    566 
    567             stream_copy_to_stream($fp, $this->_socket, $fileSize);
    568             flock($fp, LOCK_UN);
    569             fclose($fp);
    570 
    571             $resHeader = $this->read(FDFS_HEADER_LENGTH);
    572             $resInfo = FastDFS::parseHeader($resHeader);
    573 
    574             if ($resInfo['status'] !== 0) {
    575                 return false;
    576             }
    577             $resBody = $resInfo['length'] ? $this->read($resInfo['length']) : '';
    578             $groupName = trim(substr($resBody, 0, FDFS_GROUP_NAME_MAX_LEN));
    579 
    580             $filePath = trim(substr($resBody, FDFS_GROUP_NAME_MAX_LEN));
    581 
    582             if ($metas) {
    583                 $this->setFileMetaData($groupName, $filePath, $metas);
    584             }
    585 
    586             return array(
    587                 'group_name' => $groupName,
    588                 'filename' => $filePath
    589             );
    590         }
    591 
    592         /**
    593          * 
    594          * @param type $fileName
    595          * @param type $groupName
    596          * @param type $masterfile
    597          * @param type $prefix
    598          * @param type $extName
    599          * @param type $metas
    600          * @return boolean
    601          * @throws FastDFSException
    602          */
    603         public function uploadSalveFile($fileName, $groupName, $masterfile, $prefix = '', $extName = '', $metas = array()) {
    604             if (!file_exists($fileName)) {
    605                 throw new FastDFSException("salve file $fileName is not exists");
    606             }
    607 
    608             $pathInfo = pathinfo($fileName);
    609 
    610             $extName = $extName ? $extName : $pathInfo['extension'];
    611             $extLen = strlen($extName);
    612 
    613             if ($extLen > FDFS_FILE_EXT_NAME_MAX_LEN) {
    614                 throw new FastDFSException("salve file ext too long");
    615             }
    616             $fp = fopen($fileName, 'rb');
    617             flock($fp, LOCK_SH);
    618 
    619             $fileSize = filesize($fileName);
    620             $masterFilePathLen = strlen($masterfile);
    621 
    622             $reqBodyLength = 16 + FDFS_FILE_PREFIX_MAX_LEN + FDFS_FILE_EXT_NAME_MAX_LEN + $masterFilePathLen + $fileSize;
    623             $reqHeader = FastDFS::packHeader(FDFS_PROTO_CMD_UPLOAD_SLAVE_FILE, $reqBodyLength);
    624 
    625             $reqBody = pack('x4N', $masterFilePathLen) . FastDFS::packU64($fileSize) . FastDFS::padding($prefix, FDFS_FILE_PREFIX_MAX_LEN);
    626             $reqBody .= FastDFS::padding($extName, FDFS_FILE_EXT_NAME_MAX_LEN) . $masterfile;
    627 
    628             $this->send($reqHeader . $reqBody);
    629 
    630             stream_copy_to_stream($fp, $this->_socket, $fileSize);
    631             flock($fp, LOCK_UN);
    632             fclose($fp);
    633 
    634             $resHeader = $this->read(FDFS_HEADER_LENGTH);
    635             $resInfo = FastDFS::parseHeader($resHeader);
    636 
    637             if ($resInfo['status'] !== 0) {
    638                 return false;
    639             }
    640             $resBody = $resInfo['length'] ? $this->read($resInfo['length']) : '';
    641             $groupName = trim(substr($resBody, 0, FDFS_GROUP_NAME_MAX_LEN));
    642 
    643             $filePath = trim(substr($resBody, FDFS_GROUP_NAME_MAX_LEN));
    644 
    645             if ($metas) {
    646                 $this->setFileMetaData($groupName, $filePath, $metas);
    647             }
    648 
    649             return array(
    650                 'group_name' => $groupName,
    651                 'filename' => $filePath
    652             );
    653         }
    654 
    655         public function deleteFile($groupName, $fileName) {
    656             $reqBodyLen = strlen($fileName) + FDFS_GROUP_NAME_MAX_LEN;
    657             $reqHeader = FastDFS::packHeader(FDFS_PROTO_CMD_DELETE_FILE, $reqBodyLen);
    658             $reqBody = FastDFS::padding($groupName, FDFS_GROUP_NAME_MAX_LEN) . $fileName;
    659 
    660             $this->send($reqHeader . $reqBody);
    661 
    662             $resHeader = $this->read(FDFS_HEADER_LENGTH);
    663             $resInfo = FastDFS::parseHeader($resHeader);
    664 
    665             return !$resInfo['status'];
    666         }
    667 
    668         public function fileExists($groupName, $filePath) {
    669             $meta = $this->getFileMeta($groupName, $filePath);
    670 
    671             return $meta ? true : false;
    672         }
    673 
    674         public function setFileMetaData($groupName, $filePath, array $metaData, $flag = FDFS_OVERWRITE_METADATA) {
    675 
    676             $metaData = FastDFS::packMetaData($metaData);
    677             $metaDataLength = strlen($metaData);
    678             $filePathLength = strlen($filePath);
    679             $flag = $flag === FDFS_OVERWRITE_METADATA ? 'O' : 'M';
    680 
    681             $reqBodyLength = (FDFS_PROTO_PKG_LEN_SIZE * 2) + 1 + $metaDataLength + $filePathLength + FDFS_GROUP_NAME_MAX_LEN;
    682 
    683             $reqHeader = FastDFS::packHeader(FDFS_PROTO_CMD_SET_METADATA, $reqBodyLength);
    684 
    685             $reqBody = FastDFS::packU64($filePathLength) . FastDFS::packU64($metaDataLength);
    686             $reqBody .= $flag . FastDFS::padding($groupName, FDFS_GROUP_NAME_MAX_LEN) . $filePath . $metaData;
    687 
    688             $this->send($reqHeader . $reqBody);
    689 
    690             $resHeader = $this->read(FDFS_HEADER_LENGTH);
    691             $resInfo = FastDFS::parseHeader($resHeader);
    692 
    693             return !$resInfo['status'];
    694         }
    695 
    696         /**
    697          * 取得文件的元信息,如果文件不存在则,返回false,反正是一个关联数组
    698          * 
    699          * @param type $groupName
    700          * @param type $filePath
    701          * @return boolean
    702          */
    703         public function getFileMeta($groupName, $filePath) {
    704             $reqBodyLength = strlen($filePath) + FDFS_GROUP_NAME_MAX_LEN;
    705             $reqHeader = FastDFS::packHeader(FDFS_PROTO_CMD_GET_METADATA, $reqBodyLength);
    706             $reqBody = FastDFS::padding($groupName, FDFS_GROUP_NAME_MAX_LEN) . $filePath;
    707 
    708             $this->send($reqHeader . $reqBody);
    709 
    710             $resHeader = $this->read(FDFS_HEADER_LENGTH);
    711             $resInfo = FastDFS::parseHeader($resHeader);
    712 
    713             if (!!$resInfo['status']) {
    714                 return false;
    715             }
    716 
    717             $resBody = $resInfo['length'] ? $this->read($resInfo['length']) : false;
    718 
    719             return FastDFS::parseMetaData($resBody);
    720         }
    721 
    722         public function close() {
    723             fclose($this->_socket);
    724         }
    725 
    726     }
    727 
    728     class FastDFSException extends Exception {
    729         
    730     }
    731 
    732 }

    上面是api基类:

    下面是调用方式:

     1 /**
     2      * FastDFS上传文件
     3      * @param unknown $fileurl 上传文件
     4      * @param unknown $sizes 附属文件
     5      * @return string
     6      */
     7     private function applydfs($fileurl,$sizes=array()){ 9         $dfs=new FastDFS();
    10         $tracker = $dfs->tracker_get_connection();
    11         $location = "";
    12         if($dfs->active_test($tracker)){
    13             $storaged = $dfs->tracker_query_storage_store("group1",$tracker);
    14             if(!empty($sizes)){
    15                 $count = 0;
    16                 $filename = $dfs->storage_upload_by_filename($fileurl);
    17                 if(isset($filename['group_name'])&&isset($filename['filename'])){
    18                     $location =$filename['group_name']."/".$filename['filename'];
    19                 }
    20                 foreach($sizes as $key=>$val){
    21                     $snapshot_file_info =$dfs->storage_upload_slave_by_filename($val,"group1",$filename['filename'],$key);
    22                     if($snapshot_file_info){
    23                         $count++;
    24                     }
    25                 }
    26                 if($count <> count($sizes)){
    27                     $location = "";
    28                 }
    29             }else{
    30                 $filename = $dfs->storage_upload_by_filename($fileurl);
    31                 if(isset($filename['group_name'])&&isset($filename['filename'])){
    32                     $location =$filename['group_name']."/".$filename['filename'];
    33                 }
    34             }
    35         }
    36         return $location;
    37     }

    在php.ini中配置:

     1 [fastdfs]
     2 ; the base path
     3 fastdfs_client.base_path = /tmp
     4 
     5 ; connect timeout in seconds
     6 ; default value is 30s
     7 fastdfs_client.connect_timeout = 2
     8 
     9 ; network timeout in seconds
    10 ; default value is 30s
    11 fastdfs_client.network_timeout = 60
    12 
    13 ; standard log level as syslog, case insensitive, value list:
    14 ;;; emerg for emergency
    15 ;;; alert
    16 ;;; crit for critical
    17 ;;; error
    18 ;;; warn for warning
    19 ;;; notice
    20 ;;; info
    21 ;;; debug
    22 fastdfs_client.log_level = info
    23 
    24 ; set the log filename, such as /usr/local/fastdfs/logs/fastdfs_client.log
    25 ; empty for output to stderr
    26 fastdfs_client.log_filename = /tmp/fastdfs_client.log
    27 
    28 ; secret key to generate anti-steal token
    29 ; this parameter must be set when http.anti_steal.check_token set to true
    30 ; the length of the secret key should not exceed 128 bytes
    31 fastdfs_client.http.anti_steal_secret_key = 
    32 
    33 ; FastDFS cluster count, default value is 1
    34 fastdfs_client.tracker_group_count = 1
    35 
    36 ; config file of FastDFS cluster ;, based 0
    37 ; must include absolute path, such as fastdfs_client.tracker_group0
    38 ; the config file is same as conf/client.conf
    39 ; 这是你fastdfs的tracker的配置文件的路径,必须使用绝对路径,请换成你自己的路径,附件是我们开发环境和测试环境的client.conf配置
    40 ; 测试环境已经配置过,你自己的开发环境需要配置一下
    41 fastdfs_client.tracker_group0 = "E:/wamp/bin/php/php5.3.13/client.conf"
    42 
    43 ; if use connection pool
    44 ; default value is false
    45 ; since V4.05
    46 fastdfs_client.use_connection_pool = false
    47 
    48 ; connections whose the idle time exceeds this time will be closed
    49 ; unit: second
    50 ; default value is 3600
    51 ; since V4.05
    52 fastdfs_client.connection_pool_max_idle_time = 3600
    53 
    54 ; the base path
    55 fastdfs_client.base_path = /tmp
    56 
    57 ; connect timeout in seconds
    58 ; default value is 30s
    59 fastdfs_client.connect_timeout = 2
    60 
    61 ; network timeout in seconds
    62 ; default value is 30s
    63 fastdfs_client.network_timeout = 60
  • 相关阅读:
    sizeof()和 strlen()的区别 --- 个人笔记
    MySQL 生成自增流水号
    sql 逗号分隔列转行
    【转】.NET中lock的使用方法及注意事项
    【转】在一个SQL Server表中一行的多个列找出最大值
    使用 PIVOT 和 UNPIVOT
    List<T>转DataTable
    C# 分数计算类(加减乘除)
    【转】mysql执行计划介绍
    【转】SQL Server 存储:理解IAM 页
  • 原文地址:https://www.cnblogs.com/chuanheng/p/3607860.html
Copyright © 2020-2023  润新知