FastDFS php API
<?php
if (!class_exists('FastDFS', false)) {
define('FDFS_PROTO_PKG_LEN_SIZE', 8);
define('FDFS_PROTO_CMD_ACTIVE_TEST', 111);
define('FDFS_PROTO_CMD_RESP', 100);
define('FDFS_PROTO_CMD_UPLOAD_SLAVE_FILE', 21);
define('FDFS_PROTO_CMD_DELETE_FILE', 12);
define('FDFS_PROTO_CMD_GET_METADATA', 15);
define('FDFS_PROTO_CMD_SET_METADATA', 13);
//body_length + command + status
define('FDFS_HEADER_LENGTH', 10);
define('FDFS_IP_ADDRESS_SIZE', 16);
define('FDFS_FILE_EXT_NAME_MAX_LEN', 6);
define('FDFS_GROUP_NAME_MAX_LEN', 16);
define('FDFS_OVERWRITE_METADATA', 1);
define('FDFS_MERGE_METADATA', 2);
// 连接超时时间
define('FDFS_CONNECT_TIME_OUT', 5);
define('FDFS_FILE_PREFIX_MAX_LEN', 16);
//传输超时时间
define('FDFS_TRANSFER_TIME_OUT', 0);
define('FDFS_QUERY_STORE_WITHOUT_GROUP_ONE', 101);
define('FDFS_QUERY_STORE_WITH_GROUP_ONE', 104);
define('FDFS_TRACKER_QUERY_STORAGE_STORE_BODY_LEN', FDFS_GROUP_NAME_MAX_LEN + FDFS_IP_ADDRESS_SIZE + FDFS_PROTO_PKG_LEN_SIZE);
class FastDFS {
public $gConfig = array();
/**
*
* @var FastDFSTrackerClient
*/
private $tracker;
/**
*
* @var FastDFSStorageClient
*/
private $storage;
private $error = array(
'code' => 0,
'msg' => ''
);
/**
* 要使用这个类,你一定要在php的ini文件中进行fastdfs的配置
*
* @throws FastDFSException
*/
public function __construct() {
$configFile = '';
$ini = parse_ini_file(php_ini_loaded_file());
if (!isset($ini['fastdfs_client.tracker_group_count'])) {
throw new FastDFSException("no define fastdfs config");
}
for ($i = 0; $i < $ini['fastdfs_client.tracker_group_count']; $i++) {
if (isset($ini['fastdfs_client.tracker_group' . $i])) {
$configFile = $ini['fastdfs_client.tracker_group' . $i];
break;
}
}
if (!file_exists($configFile)) {
throw new FastDFSException("client config $configFile not found");
}
$this->gConfig = parse_ini_file($configFile);
list($this->gConfig['tracker_host'], $this->gConfig['tracker_port']) = explode(':', $this->gConfig['tracker_server']);
}
/**
* 获得一个tracker
*
* @return \FastDFSTrackerClient
*/
public function tracker_get_connection() {
$this->tracker = new FastDFSTrackerClient($this, $this->gConfig['tracker_host'], $this->gConfig['tracker_port']);
return $this->tracker;
}
/**
* 通过tracker获取一个stroage
*
* @param string $groupName 文件组名,当为空时,组名由tracker决定
* @param FastDFSTrackerClient $tracker
* @return \FastDFSStorageClient
*/
public function tracker_query_storage_store($groupName, FastDFSTrackerClient $tracker) {
$this->storage = new FastDFSStorageClient($this, $groupName, $tracker);
return $this->storage;
}
/**
* 测试一下tracker服务器是否正常
*
* @param FastDFSTrackerClient $tracker
* @return boolean
*/
public function active_test(FastDFSTrackerClient $tracker = null) {
$this->initTrackerAndStorage($tracker);
$header = self::packHeader(FDFS_PROTO_CMD_ACTIVE_TEST, 0);
$tracker->send($header);
$resHeader = self::parseHeader($tracker->read(FDFS_HEADER_LENGTH));
return $resHeader['status'] == 0 ? true : false;
}
public function get_last_error_no() {
return $this->error['code'];
}
public function add_error($errorNo, $info) {
$this->error['code'] = $errorNo;
$this->error['msg'] = $info;
}
public function get_last_error_info() {
return $this->error['msg'];
}
/**
* 在storage中删除一个文件
*
* @param string $groupName 文件所在的组名
* @param string $remoteFile 要删除的文件路径
* @param FastDFSStorageClient $tracker
* @param FastDFSStorageClient $storage
*/
public function storage_delete_file($groupName, $remoteFile, FastDFSStorageClient $tracker, FastDFSStorageClient $storage) {
$this->initTrackerAndStorage($tracker, $storage, $groupName);
$this->storage->deleteFile($groupName, $remoteFile);
}
/**
* 往storage中上传一个文件
*
* @param string $localFile 你本地的文件路径
* @param string $extName 文件的扩展名,当名优提供扩展名时,会自动取文件的扩展名
* @param array $metas 文件的附加信息
* @param string $groupName 所在的组名,可以为空,为空时,由tracker决定
* @param FastDFSTrackerClient $tracker
* @param FastDFSStorageClient $storage
*/
public function storage_upload_by_filename($localFile, $extName = '', $metas = array(), $groupName = '', FastDFSTrackerClient $tracker = null, FastDFSStorageClient $storage = null) {
$this->initTrackerAndStorage($tracker, $storage, $groupName);
return $this->storage->uploadByFilename($localFile, $extName, $metas);
}
/**
* 上传一个文件的附属文件,主要使用一个图片有缩略图的情况下
*
* @param string $localFile 本地文件的路径,缩略图的文件路径
* @param string $groupName 组名,最好和主文件在同一个组
* @param string $masterFileName 主文件名
* @param string $prefix 文件的前缀
* @param string $extName 文件的后缀,可以为空,为空时,由tracker决定
* @param array $meta 附件信息
* @param FastDFSTrackerClient $tracker
* @param FastDFSStorageClient $storage
*/
public function storage_upload_slave_by_filename($localFile, $groupName, $masterFileName, $prefix = '', $extName = '', $meta = array(), FastDFSTrackerClient $tracker = null, FastDFSStorageClient $storage = null) {
$this->initTrackerAndStorage($tracker, $storage, $groupName);
/*echo $localFile."<br/>".$groupName."<br/>".$masterFileName."<br/>".$prefix;
exit;*/
return $this->storage->uploadSalveFile($localFile, $groupName, $masterFileName, $prefix, $extName, $meta);
}
/**
* 检查这个文件是否已经存在
*
* @param string $groupName 文件所在组名
* @param string $remoteFile 文件在storage中的名字
* @param FastDFSStorageClient $tracker
* @param FastDFSStorageClient $storage
*/
public function storage_file_exist($groupName, $remoteFile, FastDFSTrackerClient $tracker, FastDFSStorageClient $storage) {
$this->initTrackerAndStorage($tracker, $storage, $groupName);
return $this->storage->fileExists($groupName, $remoteFile);
}
public function close() {
if ($this->tracker) {
$this->tracker->close();
$this->tracker = null;
}
}
public function tracker_close_all_connections() {
$this->close();
if (!$this->storage) {
$this->storage->close();
}
}
public static function padding($str, $len) {
$str_len = strlen($str);
return $str_len > $len ? substr($str, 0, $len) : $str . pack('x' . ($len - $str_len));
}
/**
*
* @param int $command
* @param int $length
* @return bytes
*/
public static function packHeader($command, $length = 0) {
return self::packU64($length) . pack('Cx', $command);
}
public static function packMetaData($data) {
$S1 = "\x01";
$S2 = "\x02";
$list = array();
foreach ($data as $key => $val) {
$list[] = $key . $S2 . $val;
};
return implode($S1, $list);
}
public static function parseMetaData($data) {
$S1 = "\x01";
$S2 = "\x02";
$arr = explode($S1, $data);
$result = array();
foreach ($arr as $val) {
list($k, $v) = explode($S2, $val);
$result[$k] = $v;
}
return $result;
}
public static function parseHeader($str, $len = FDFS_HEADER_LENGTH) {
assert(strlen($str) === $len);
$result = unpack('C10', $str);
$length = self::unpackU64(substr($str, 0, 8));
$command = $result[9];
$status = $result[10];
return array(
'length' => $length,
'command' => $command,
'status' => $status
);
}
/**
* From: sphinxapi.php
*/
private static function unpackU64($v) {
list ( $hi, $lo ) = array_values(unpack("N*N*", $v));
if (PHP_INT_SIZE >= 8) {
if ($hi < 0)
$hi += (1 << 32); // because php 5.2.2 to 5.2.5 is totally fucked up again
if ($lo < 0)
$lo += (1 << 32);
// x64, int
if ($hi <= 2147483647)
return ($hi << 32) + $lo;
// x64, bcmath
if (function_exists("bcmul"))
return bcadd($lo, bcmul($hi, "4294967296"));
// x64, no-bcmath
$C = 100000;
$h = ((int) ($hi / $C) << 32) + (int) ($lo / $C);
$l = (($hi % $C) << 32) + ($lo % $C);
if ($l > $C) {
$h += (int) ($l / $C);
$l = $l % $C;
}
if ($h == 0)
return $l;
return sprintf("%d%05d", $h, $l);
}
// x32, int
if ($hi == 0) {
if ($lo > 0)
return $lo;
return sprintf("%u", $lo);
}
$hi = sprintf("%u", $hi);
$lo = sprintf("%u", $lo);
// x32, bcmath
if (function_exists("bcmul"))
return bcadd($lo, bcmul($hi, "4294967296"));
// x32, no-bcmath
$hi = (float) $hi;
$lo = (float) $lo;
$q = floor($hi / 10000000.0);
$r = $hi - $q * 10000000.0;
$m = $lo + $r * 4967296.0;
$mq = floor($m / 10000000.0);
$l = $m - $mq * 10000000.0;
$h = $q * 4294967296.0 + $r * 429.0 + $mq;
$h = sprintf("%.0f", $h);
$l = sprintf("%07.0f", $l);
if ($h == "0")
return sprintf("%.0f", (float) $l);
return $h . $l;
}
private function initTrackerAndStorage(FastDFSTrackerClient $tracker = null, FastDFSStorageClient $storage = null, $groupName = '') {
$reNewStorage = false;
if ($tracker && $tracker !== $this->tracker) {
$this->tracker_get_connection();
}
if (($storage && $storage !== $this->storage) || $reNewStorage) {
$this->tracker_query_storage_store($groupName, $this->tracker);
}
}
/**
* From: sphinxapi.php
*/
public static function packU64($v) {
assert(is_numeric($v));
// x64
if (PHP_INT_SIZE >= 8) {
assert($v >= 0);
// x64, int
if (is_int($v))
return pack("NN", $v >> 32, $v & 0xFFFFFFFF);
// x64, bcmath
if (function_exists("bcmul")) {
$h = bcdiv($v, 4294967296, 0);
$l = bcmod($v, 4294967296);
return pack("NN", $h, $l);
}
// x64, no-bcmath
$p = max(0, strlen($v) - 13);
$lo = (int) substr($v, $p);
$hi = (int) substr($v, 0, $p);
$m = $lo + $hi * 1316134912;
$l = $m % 4294967296;
$h = $hi * 2328 + (int) ($m / 4294967296);
return pack("NN", $h, $l);
}
// x32, int
if (is_int($v))
return pack("NN", 0, $v);
// x32, bcmath
if (function_exists("bcmul")) {
$h = bcdiv($v, "4294967296", 0);
$l = bcmod($v, "4294967296");
return pack("NN", (float) $h, (float) $l); // conversion to float is intentional; int would lose 31st bit
}
// x32, no-bcmath
$p = max(0, strlen($v) - 13);
$lo = (float) substr($v, $p);
$hi = (float) substr($v, 0, $p);
$m = $lo + $hi * 1316134912.0;
$q = floor($m / 4294967296.0);
$l = $m - ($q * 4294967296.0);
$h = $hi * 2328.0 + $q;
return pack("NN", $h, $l);
}
}
abstract class FastDFSBase {
abstract public function getSocket();
abstract public function close();
public function read($length, $socket = null) {
if (!$socket) {
$socket = $this->getSocket();
}
if (feof($socket)) {
throw new FastDFS_Exception('connection unexpectedly closed (timed out?)', $this->_errno);
}
$data = stream_get_contents($socket, $length);
assert($length === strlen($data));
return $data;
}
public function send($data, $length = 0, $socket = null) {
if (!$socket) {
$socket = $this->getSocket();
}
if (!$length) {
$length = strlen($data);
}
if (feof($socket) || fwrite($socket, $data, $length) !== $length) {
throw new Exception('connection unexpectedly closed (timed out?)');
}
return true;
}
}
class FastDFSTrackerClient extends FastDFSBase {
private $host;
private $port;
/**
*
* @var FastDFS
*/
private $dfs;
private $_socket;
public function __construct(FastDFS &$dfs, $host, $port) {
$this->host = $host;
$this->port = $port;
$this->dfs = $dfs;
$this->_socket = @fsockopen("tcp://$host", $port, $errno, $errstr, $this->dfs->gConfig['connect_timeout']);
if (!$this->_socket) {
$this->dfs->add_error(-2, $errstr);
}
}
public function getSocket() {
return $this->_socket;
}
public function close() {
fclose($this->_socket);
}
}
class FastDFSStorageClient extends FastDFSBase {
private $groupName;
/**
*
* @var FastDFSTrackerClient
*/
private $tracker;
/**
*
* @var FastDFS
*/
private $dfs;
private $_socket;
private $host;
private $port;
private $storeIndex;
public function __construct(FastDFS &$dfs, $groupName, FastDFSTrackerClient $tracker) {
$this->tracker = $tracker;
$this->dfs = $dfs;
$reqBody = '';
if ($groupName) {
$cmd = FDFS_QUERY_STORE_WITH_GROUP_ONE;
$len = FDFS_GROUP_NAME_MAX_LEN;
$reqBody = FastDFS::padding($groupName, $len);
} else {
$cmd = FDFS_QUERY_STORE_WITHOUT_GROUP_ONE;
$len = 0;
}
$reqHeader = FastDFS::packHeader($cmd, $len);
$this->tracker->send($reqHeader . $reqBody);
$resHeader = $this->tracker->read(FDFS_HEADER_LENGTH);
$resInfo = FastDFS::parseHeader($resHeader);
if ($resInfo['status'] != 0) {
throw new Exception("something wrong with get storage by group name", $resInfo['status']);
}
$resBody = !!$resInfo['length'] ? $this->tracker->read($resInfo['length']) : '';
$this->groupName = trim(substr($resBody, 0, FDFS_GROUP_NAME_MAX_LEN));
$this->host = trim(substr($resBody, FDFS_GROUP_NAME_MAX_LEN, FDFS_IP_ADDRESS_SIZE + 1));
list(,, $this->port) = unpack('N2', substr($resBody, FDFS_GROUP_NAME_MAX_LEN + FDFS_IP_ADDRESS_SIZE - 1, FDFS_PROTO_PKG_LEN_SIZE));
$this->storeIndex = ord(substr($resBody, -1));
$this->_socket = @fsockopen($this->host, $this->port, $errno, $errstr, $this->dfs->gConfig['connect_timeout']);
if (!$this->_socket) {
$this->dfs->add_error($errno, $errstr);
}
}
public function getSocket() {
return $this->_socket;
}
public function getStorePathIndex() {
return $this->storeIndex;
}
public function uploadByFilename($localFile, $extName, $metas) {
if (!file_exists($localFile)) {
throw new FastDFSException("$localFile file is not exists");
}
$pathInfo = pathinfo($localFile);
$extName = $extName ? $extName : $pathInfo['extension'];
$extLen = strlen($extName);
if ($extLen > FDFS_FILE_EXT_NAME_MAX_LEN) {
throw new FastDFSException("file ext too long");
}
$fp = fopen($localFile, 'rb');
flock($fp, LOCK_SH);
$fileSize = filesize($localFile);
$reqBodyLen = 1 + FDFS_PROTO_PKG_LEN_SIZE + FDFS_FILE_EXT_NAME_MAX_LEN + $fileSize;
$reqHeader = FastDFS::packHeader(11, $reqBodyLen);
$reqBody = pack('C', $this->getStorePathIndex()) . FastDFS::packU64($fileSize) . FastDFS::padding($extName, FDFS_FILE_EXT_NAME_MAX_LEN);
$this->send($reqHeader . $reqBody);
stream_copy_to_stream($fp, $this->_socket, $fileSize);
flock($fp, LOCK_UN);
fclose($fp);
$resHeader = $this->read(FDFS_HEADER_LENGTH);
$resInfo = FastDFS::parseHeader($resHeader);
if ($resInfo['status'] !== 0) {
return false;
}
$resBody = $resInfo['length'] ? $this->read($resInfo['length']) : '';
$groupName = trim(substr($resBody, 0, FDFS_GROUP_NAME_MAX_LEN));
$filePath = trim(substr($resBody, FDFS_GROUP_NAME_MAX_LEN));
if ($metas) {
$this->setFileMetaData($groupName, $filePath, $metas);
}
return array(
'group_name' => $groupName,
'filename' => $filePath
);
}
/**
*
* @param type $fileName
* @param type $groupName
* @param type $masterfile
* @param type $prefix
* @param type $extName
* @param type $metas
* @return boolean
* @throws FastDFSException
*/
public function uploadSalveFile($fileName, $groupName, $masterfile, $prefix = '', $extName = '', $metas = array()) {
if (!file_exists($fileName)) {
throw new FastDFSException("salve file $fileName is not exists");
}
$pathInfo = pathinfo($fileName);
$extName = $extName ? $extName : $pathInfo['extension'];
$extLen = strlen($extName);
if ($extLen > FDFS_FILE_EXT_NAME_MAX_LEN) {
throw new FastDFSException("salve file ext too long");
}
$fp = fopen($fileName, 'rb');
flock($fp, LOCK_SH);
$fileSize = filesize($fileName);
$masterFilePathLen = strlen($masterfile);
$reqBodyLength = 16 + FDFS_FILE_PREFIX_MAX_LEN + FDFS_FILE_EXT_NAME_MAX_LEN + $masterFilePathLen + $fileSize;
$reqHeader = FastDFS::packHeader(FDFS_PROTO_CMD_UPLOAD_SLAVE_FILE, $reqBodyLength);
$reqBody = pack('x4N', $masterFilePathLen) . FastDFS::packU64($fileSize) . FastDFS::padding($prefix, FDFS_FILE_PREFIX_MAX_LEN);
$reqBody .= FastDFS::padding($extName, FDFS_FILE_EXT_NAME_MAX_LEN) . $masterfile;
$this->send($reqHeader . $reqBody);
stream_copy_to_stream($fp, $this->_socket, $fileSize);
flock($fp, LOCK_UN);
fclose($fp);
$resHeader = $this->read(FDFS_HEADER_LENGTH);
$resInfo = FastDFS::parseHeader($resHeader);
if ($resInfo['status'] !== 0) {
return false;
}
$resBody = $resInfo['length'] ? $this->read($resInfo['length']) : '';
$groupName = trim(substr($resBody, 0, FDFS_GROUP_NAME_MAX_LEN));
$filePath = trim(substr($resBody, FDFS_GROUP_NAME_MAX_LEN));
if ($metas) {
$this->setFileMetaData($groupName, $filePath, $metas);
}
return array(
'group_name' => $groupName,
'filename' => $filePath
);
}
public function deleteFile($groupName, $fileName) {
$reqBodyLen = strlen($fileName) + FDFS_GROUP_NAME_MAX_LEN;
$reqHeader = FastDFS::packHeader(FDFS_PROTO_CMD_DELETE_FILE, $reqBodyLen);
$reqBody = FastDFS::padding($groupName, FDFS_GROUP_NAME_MAX_LEN) . $fileName;
$this->send($reqHeader . $reqBody);
$resHeader = $this->read(FDFS_HEADER_LENGTH);
$resInfo = FastDFS::parseHeader($resHeader);
return !$resInfo['status'];
}
public function fileExists($groupName, $filePath) {
$meta = $this->getFileMeta($groupName, $filePath);
return $meta ? true : false;
}
public function setFileMetaData($groupName, $filePath, array $metaData, $flag = FDFS_OVERWRITE_METADATA) {
$metaData = FastDFS::packMetaData($metaData);
$metaDataLength = strlen($metaData);
$filePathLength = strlen($filePath);
$flag = $flag === FDFS_OVERWRITE_METADATA ? 'O' : 'M';
$reqBodyLength = (FDFS_PROTO_PKG_LEN_SIZE * 2) + 1 + $metaDataLength + $filePathLength + FDFS_GROUP_NAME_MAX_LEN;
$reqHeader = FastDFS::packHeader(FDFS_PROTO_CMD_SET_METADATA, $reqBodyLength);
$reqBody = FastDFS::packU64($filePathLength) . FastDFS::packU64($metaDataLength);
$reqBody .= $flag . FastDFS::padding($groupName, FDFS_GROUP_NAME_MAX_LEN) . $filePath . $metaData;
$this->send($reqHeader . $reqBody);
$resHeader = $this->read(FDFS_HEADER_LENGTH);
$resInfo = FastDFS::parseHeader($resHeader);
return !$resInfo['status'];
}
/**
* 取得文件的元信息,如果文件不存在则,返回false,反正是一个关联数组
*
* @param type $groupName
* @param type $filePath
* @return boolean
*/
public function getFileMeta($groupName, $filePath) {
$reqBodyLength = strlen($filePath) + FDFS_GROUP_NAME_MAX_LEN;
$reqHeader = FastDFS::packHeader(FDFS_PROTO_CMD_GET_METADATA, $reqBodyLength);
$reqBody = FastDFS::padding($groupName, FDFS_GROUP_NAME_MAX_LEN) . $filePath;
$this->send($reqHeader . $reqBody);
$resHeader = $this->read(FDFS_HEADER_LENGTH);
$resInfo = FastDFS::parseHeader($resHeader);
if (!!$resInfo['status']) {
return false;
}
$resBody = $resInfo['length'] ? $this->read($resInfo['length']) : false;
return FastDFS::parseMetaData($resBody);
}
public function close() {
fclose($this->_socket);
}
}
class FastDFSException extends Exception {
}
}
上面是api基类:
下面是调用方式:
/**
* FastDFS上传文件
* @param unknown $fileurl 上传文件
* @param unknown $sizes 附属文件
* @return string
*/
private function applydfs($fileurl,$sizes=array()){ $dfs=new FastDFS();
$tracker = $dfs->tracker_get_connection();
$location = "";
if($dfs->active_test($tracker)){
$storaged = $dfs->tracker_query_storage_store("group1",$tracker);
if(!empty($sizes)){
$count = 0;
$filename = $dfs->storage_upload_by_filename($fileurl);
if(isset($filename['group_name'])&&isset($filename['filename'])){
$location =$filename['group_name']."/".$filename['filename'];
}
foreach($sizes as $key=>$val){
$snapshot_file_info =$dfs->storage_upload_slave_by_filename($val,"group1",$filename['filename'],$key);
if($snapshot_file_info){
$count++;
}
}
if($count <> count($sizes)){
$location = "";
}
}else{
$filename = $dfs->storage_upload_by_filename($fileurl);
if(isset($filename['group_name'])&&isset($filename['filename'])){
$location =$filename['group_name']."/".$filename['filename'];
}
}
}
return $location;
}
在php.ini中配置:
[fastdfs]
; the base path
fastdfs_client.base_path = /tmp ; connect timeout in seconds
; default value is 30s
fastdfs_client.connect_timeout = 2 ; network timeout in seconds
; default value is 30s
fastdfs_client.network_timeout = 60 ; standard log level as syslog, case insensitive, value list:
;;; emerg for emergency
;;; alert
;;; crit for critical
;;; error
;;; warn for warning
;;; notice
;;; info
;;; debug
fastdfs_client.log_level = info ; set the log filename, such as /usr/local/fastdfs/logs/fastdfs_client.log
; empty for output to stderr
fastdfs_client.log_filename = /tmp/fastdfs_client.log ; secret key to generate anti-steal token
; this parameter must be set when http.anti_steal.check_token set to true
; the length of the secret key should not exceed 128 bytes
fastdfs_client.http.anti_steal_secret_key = ; FastDFS cluster count, default value is 1
fastdfs_client.tracker_group_count = 1 ; config file of FastDFS cluster ;, based 0
; must include absolute path, such as fastdfs_client.tracker_group0
; the config file is same as conf/client.conf
; 这是你fastdfs的tracker的配置文件的路径,必须使用绝对路径,请换成你自己的路径,附件是我们开发环境和测试环境的client.conf配置
; 测试环境已经配置过,你自己的开发环境需要配置一下
fastdfs_client.tracker_group0 = "E:/wamp/bin/php/php5.3.13/client.conf" ; if use connection pool
; default value is false
; since V4.05
fastdfs_client.use_connection_pool = false ; connections whose the idle time exceeds this time will be closed
; unit: second
; default value is 3600
; since V4.05
fastdfs_client.connection_pool_max_idle_time = 3600 ; the base path
fastdfs_client.base_path = /tmp ; connect timeout in seconds
; default value is 30s
fastdfs_client.connect_timeout = 2 ; network timeout in seconds
; default value is 30s
fastdfs_client.network_timeout = 60
FastDFS php API的更多相关文章
- FastDFS接口API文档说明
FastDFS接口API文档说明 时间:2012-03-17 来源:R9IT 作者:R9传奇 一.命令行的上传: 上传命令1. /usr/local/bin/fdfs_upload_file conf ...
- FastDFS的配置、部署与API使用解读(2)以字节方式上传文件的客户端代码(转)
本文来自 诗商·柳惊鸿 Poechant CSDN博客,转载请注明源地址:FastDFS的配置.部署与API使用解读(2)上传文件到FastDFS分布式文件系统的客户端代码 在阅读本文之前,请您先通过 ...
- FastDFS.Client操作文件服务器
1.配置文件设置 <configSections> <section name="fastdfs" type="FastDFS.Client.Confi ...
- FASTDFS 5X安装
FASTDFS 5X安装 http://www.wingdevops.com/?p=603 流行的开源分布式文件系统有很多,FastDFS 是国人在mogileFS的基础上进行改进的key-value ...
- 用FastDFS一步步搭建文件管理系统
一.FastDFS介绍 FastDFS开源地址:https://github.com/happyfish100 参考:分布式文件系统FastDFS设计原理 参考:FastDFS分布式文件系统 个人封装 ...
- FastDFS分布式存储实战
<FastDFS分布式存储实战> 技术选型 FastDFS相关组件及原理 FastDFS介绍 FastDFS架构 FastDFS工作流程 上传 同步机制 下载 文件合并原理 实验环境说明 ...
- (转)FastDFS文件存储
一.FastDFS介绍 FastDFS开源地址:https://github.com/happyfish100 参考:分布式文件系统FastDFS设计原理 参考:FastDFS分布式文件系统 个人封装 ...
- fastdfs安装与配置
FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了大容量存储和负载均衡的问题.特别适合以文件为载体的在线服务,如相 ...
- FastDFS:搭建文件管理系统
文章转自:https://www.cnblogs.com/chiangchou/p/fastdfs.html#_label1 一.FastDFS介绍 FastDFS开源地址:https://githu ...
随机推荐
- jQuery中的 return false, e.preventDefault(), e.stopPropagation()的区别
e.stopPropagation()阻止事件冒泡 <html><head> <title></title> <script sr ...
- 准备战争“软测试”之DB基础知识
"数据库"东西这个陌生和数据,进入提高班,从第二年开始接触,的项目还是自考的学习加起来也有3遍了.这仅仅是一个開始,软考又要对数据库进行全面的分析,那么如今就让我们再一次剖析它吧! ...
- C#快递跟踪(基于快递100深度定制)
本文主要介绍快递跟踪的相关信息.如根据快递单号预测所属快递公司,判断快递是否已被签收,以及改良官方model后可在不用申请授权的情况下实现json,html,xml及text等多种格式以及单行多行,降 ...
- Cocos2d-x之MenuItem
***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...
- Android实现“是否退出”对话框和“带图标的列表”对话框
今天我们学习的内容是实现两种对话框(Dialog),第一种是询问是否退出对话框,另外一种是带图标的列表对话框,程序的执行效果是,我们点击button1的时候,弹出第一种对话框,我们点击button2的 ...
- Redis 3.0集群搭建/配置/FAQ
·声明 1,已官网中文教程为基础,边看边学,结合环境现状搭建. 2,哥对Ruby不热爱.不熟悉.不感冒,所述内容如有疑义请谅解. 3,3.0官说集群还在测试中,其实用用也还算马马虎虎,对外集群API真 ...
- Cocos2D-X2.2.3学习笔记3(内存管理)
本章节介绍例如以下: 1.C/C++内存管理机制 2.引用计数机制 3.自己主动释放机制 1.C/C++内存管理机制 相信仅仅要懂oop的都知道NEW这个keyword吧,这个通俗点说事实上就是创建对 ...
- OpenVPN多实例优化的思考过程
1.sss 当构建组件之间的关系已经错综复杂到接近于一张全然图的时候,就要换一个思路了,或者你须要重构整个系统,或者你将又一次实现一个. 2.TAP网卡和TUN网卡 2.1.TAP的优势 1.方便组网 ...
- IIS7 URL Rewrite 用法实例
原文:IIS7 URL Rewrite 用法实例 很友好的URL地址,使访问的人很容易记住.要求你的用户记住" http://www.contoso.com/article.aspx?id= ...
- 【 D3.js 入门系列 --- 9.6 】 生产的包图
我的个人博客是:www.ourd3js.com csdn博客为:blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 打包图( Pack ).用于包括与被包括的关系,也表示各个对象的权重, ...