Source for file saestorage.class.php
Documentation is available at saestorage.class.php
* This is the PHP SDK API For SAE Storage Service.
* See COPYING for license information.
* @copyright Copyright (c) 2013, Sina App Engine.
include_once dirname(__FILE__
) .
'/swiftclient.php';
private $errMsg =
'success';
private $basedomain =
'stor.sinaapp.com';
private $cdndomain =
'sae.sinacdn.com';
* @param string $accessKey AccessKey of Appname
* @param string $secretKey SecretKey of Appname
function __construct($accessKey =
NULL, $secretKey =
NULL)
$this->accessKey =
SAE_ACCESSKEY;
$this->accessKey =
$accessKey;
$this->secretKey =
SAE_SECRETKEY;
$this->secretKey =
$secretKey;
$this->appName =
$_SERVER[ 'HTTP_APPNAME' ];
$this->swift_conn =
new CF_Connection($this->accessKey,$this->secretKey,$this->appName);
* @param string $akey,应用的accessKey
* @param string $skey,应用的secretKey
* @param string _appName, 应用名
public function setAuth( $akey , $skey , $_appName =
'' )
$this->appName =
$_SERVER[ 'HTTP_APPNAME' ];
$this->appName =
$_appName;
$this->accessKey =
$akey;
$this->secretKey =
$skey;
$this->swift_conn =
new CF_Connection($this->accessKey,$this->secretKey,$this->appName);
$ret =
$this->errMsg.
" url(".
$this->filePath.
")";
$this->errMsg =
'Success';
public function getAppname()
* $stor = new SaeStorage();
* $cdn_url = $stor->getCDNUrl("domain","cdn_test.txt");
* @param string $domain Domain name
* @param string $filename Filename you save
public function getCDNUrl( $domain, $filename )
$filename =
$this->formatFilename($filename);
$filePath =
"http://".
$this->appName.
'.'.
$this->cdndomain .
"/.app-stor/$domain/$filename";
$domain =
$this->getDom($domain);
$filePath =
"http://".
$domain.
'.'.
$this->basedomain .
"/$filename";
* #Get the url of a stored file
* $stor = new SaeStorage();
* $file_url = $stor->getUrl("domain","cdn_test.txt");
* @param string $domain Domain name
* @param string $filename Filename you save
public function getUrl( $domain, $filename )
$filename =
$this->formatFilename($filename);
$domain =
$this->getDom($domain);
$this->filePath =
"http://".
$domain.
'.'.
$this->basedomain .
"/$filename";
* @param string $filename The filename you wanna set
private function setUrl( $domain , $filename )
$filename =
$this->formatFilename($filename);
$this->filePath =
"http://".
$domain.
'.'.
$this->basedomain .
"/$filename";
* # Write some content into a storage file
* $storage = new SaeStorage();
* $destFileName = 'write_test.txt';
* $content = 'Hello,I am from the method of write'
* $attr = array('encoding'=>'gzip');
* $result = $storage->write($domain,$destFileName, $content, -1, $attr, true);
* @param string $domain Domain name
* @param string $destFileName The destiny fileName.
* @param string $content The content of the file
* @param int $size The length of file content,the overflower will be truncated and by default there is no limit.
* @param array $attr File attributes, set attributes refer to SaeStorage :: setFileAttr () method
* @param boolean $compress
* #Note: Whether gzip compression.
* If true, the file after gzip compression and then stored in Storage,
* often associated with $attr=array('encoding'=>'gzip') used in conjunction
* #Note: If success,return the url of the file
public function write( $domain, $destFileName, $content, $size = -
1, $attr =
array(), $compress =
false )
$domain =
$this->parseDomain(trim($domain));
$destFileName =
$this->formatFilename($destFileName);
if (empty($domain) or empty($destFileName)) {
$this->errMsg =
'The value of parameter (domain,destFileName,content) can not be empty!';
$content =
substr( $content, 0, $size );
$srcFileName =
tempnam(SAE_TMP_PATH, 'SAE_STOR_UPLOAD');
$re =
$this->upload($domain, $destFileName, $srcFileName, $attr);
* $storage = new SaeStorage();
* $destFileName = 'write_test.txt';
* $srcFileName = $_FILE['tmp_name']
* $attr = array('encoding'=>'gzip');
* $result = $storage->upload($domain,$destFileName, $srcFileName, -1, $attr, true);
* The `domain` must be Exist
* @param string $domain Domain name
* @param string $destFileName The destiny fileName.
* @param string $srcFileName The source of the uoload file
* @param array $attr File attributes, set attributes refer to SaeStorage :: setFileAttr () method
* @param boolean $compress
* #Note: Whether gzip compression.
* If true, the file after gzip compression and then stored in Storage,
* often associated with $attr=array('encoding'=>'gzip') used in conjunction
* #Note: If success,return the url of the file
public function upload( $domain, $destFileName, $srcFileName, $attr =
array(), $compress =
false )
$domain =
$this->parseDomain(trim($domain));
$destFileName =
$this->formatFilename($destFileName);
if ( empty($domain) or empty($destFileName) or empty($srcFileName)) {
$this->errMsg =
'The value of parameter (domain,destFile,srcFileName) can not be empty!';
$srcFileNew =
tempnam( SAE_TMP_PATH, 'SAE_STOR_UPLOAD');
$srcFileName =
$srcFileNew;
$parseAttr =
$this->parseFileAttr($attr);
$this->setUrl( $this->getDom($domain), $destFileName );
$container =
$this->swift_conn->get_container($domain);
$this->errMsg =
$e->getMessage();
$object =
$container->create_object($destFileName);
$object->__getMimeType($destFileName);
$this->errMsg =
$e->getMessage();
$result =
$object->load_from_filename($srcFileName);
return $this->getUrl($domain,$destFileName);
$this->errMsg =
sprintf('Failed to store to filesystem!(%s)',$e->getMessage());
* // 列出 Domain 下所有路径以photo开头的文件
* $stor = new SaeStorage();
* while ( $ret = $stor->getList("test", "photo", 100, $num ) ) {
* foreach($ret as $file) {
* echo "\nTOTAL: {$num} files\n";
* @param string $domain 存储域,在在线管理平台.storage页面可进行管理
* @param string $prefix 路径前缀
* @param int $limit 返回条数,最大100条,默认10条
* @param int $offset 起始条数。limit与offset之和最大为10000,超过此范围无法列出。
* @return array 执行成功时返回文件列表数组,否则返回false
public function getList( $domain, $prefix=
NULL, $limit=
10, $offset =
0 )
$domain =
$this->parseDomain(trim($domain));
$this->errMsg =
'The value of parameter (domain) can not be empty!';
$container =
$this->swift_conn->get_container($domain);
$this->errMsg =
$e->getMessage();
$list_detail =
$container->get_objects($limit,NULL,$prefix);
$list_detail_array =
$this->std_class_object_to_array($list_detail);
$list_detail_new =
array();
foreach($list_detail_array as $small) {
$list_detail_new[] =
$small['name'];
$total_num =
count($list_detail_new);
if ( $total_num <
$offset ) return array();
for ( $i =
$offset; $i <
$total_num; $i++
) {
$file_list[] =
$list_detail_new[$i];
$this->errMsg =
$e->getMessage();
* @param string $domain 存储域
* @param string $path 目录地址
* @param int $limit 单次返回数量限制,默认100,最大1000
* @param int $offset 起始条数
* @param int $fold 是否折叠目录
* @return array 执行成功时返回列表,否则返回false
public function getListByPath( $domain, $path =
NULL, $limit =
100, $offset =
0, $fold =
true )
$domain =
$this->parseDomain(trim($domain));
$this->errMsg =
'the value of parameter (domain) can not be empty!';
$container =
$this->swift_conn->get_container($domain);
$this->errMsg =
$e->getMessage();
if($path !=
''){$path =
$path.
"/";}
$result =
$container->get_objects($limit,NULL,$path,NULL,$delimiter,true);
$total_num =
count($result);
if ( $total_num <
$offset ) return array();
for ( $i =
$offset; $i <
$total_num; $i++
) {
$file_list[] =
$result[$i];
$list['files'] =
array();
foreach ( $result as $item ) {
if ( isset
( $item['subdir'] ) ) {
'fullName' =>
$item['subdir']
'fullName' =>
$item['name'],
'length' =>
$item['bytes'],
'uploadTime' =>
strtotime($item['last_modified']) +
60 *
60 *
8
if ( isset
($item['X-Sws-Object-Meta-Expires-Rule']) ) $file['expires'] =
$headers['X-Sws-Object-Meta-Expires-Rule'];
$list['files'][] =
$file;
foreach ( $result as $item ) {
'fullName' =>
$item['name'],
'length' =>
$item['bytes'],
'uploadTime' =>
strtotime($item['last_modified'])
$this->errMsg =
$e->getMessage();
* @param string $domain 存储域,在在线管理平台.storage页面可进行管理
* @param string $path 目录(暂没实现)
* @return array 执行成功时返回文件数,否则返回false
$domain =
$this->parseDomain(trim($domain));
$this->errMsg =
'the value of parameter (domain) can not be empty!';
$info =
$this->swift_conn->get_container($domain);
$info_array =
$this->std_class_object_to_array($info);
return $info_array['object_count'];
$this->errMsg =
$e->getMessage();
* @param string $domain 存储域
* @param string $filename 文件地址
* @param array $attrKey 属性值,如 array("fileName", "length"),当attrKey为空时,以关联数组方式返回该文件的所有属性。
* @return array 执行成功以数组方式返回文件属性,否则返回false
public function getAttr( $domain, $filename, $attrKey=
array() )
$domain =
$this->parseDomain(trim($domain));
$filename =
$this->formatFilename($filename);
if ( $domain ==
'' ||
$filename ==
'' )
$this->errMsg =
'the value of parameter (domain,filename) can not be empty!';
$container =
$this->swift_conn->get_container($domain);
$this->errMsg =
$e->getMessage();
$this->setUrl( $this->getDom($domain), $filename );
$object =
$container->get_object($filename);
$object =
$this->std_class_object_to_array($object);
if ( !empty($object['last_modified']) ) {
'fileName'=>
$object['name'],
'datetime'=>
strtotime($object['last_modified']),
'content_type'=>
$object['content_type'],
'length'=>
$object['content_length'],
'md5sum'=>
$object['etag'],
'expires'=>
array_key_exists('Expires', $object['metadata'])?
$object['metadata']['Expires']:
NULL
if (count($attrKey) !=
0) {
foreach ($attrKey as $small) {
$tmp_array[$small] =
$file_attr[$small];
$this->errMsg =
$e->getMessage();
* @param string $domain 存储域
* @param string $filename 文件地址
$domain =
$this->parseDomain(trim($domain));
$filename =
$this->formatFilename($filename);
if ( $domain ==
'' ||
$filename ==
'' )
$this->errMsg =
'the value of parameter (domain,filename) can not be empty!';
$file_exist =
$this->getAttr($domain,$filename);
return ($file_exist ===
false)?
false:
true;
* @param string $filename
* @return string 成功时返回文件内容,否则返回false
public function read( $domain, $filename )
$domain =
$this->parseDomain(trim($domain));
$filename =
$this->formatFilename($filename);
if ( $domain ==
'' ||
$filename ==
'' )
$this->errMsg =
'the value of parameter (domain,filename) can not be empty!';
$this->setUrl( $this->getDom($domain), $filename );
$container =
$this->swift_conn->get_container($domain);
$this->errMsg =
$e->getMessage();
$object =
$container->get_object($filename);
$this->errMsg =
$e->getMessage();
$this->errMsg =
$e->getMessage();
* @param string $filename
public function delete( $domain, $filename )
$domain =
$this->parseDomain(trim($domain));
//$filename = $this->formatFilename($filename);
if ( $domain ==
'' ||
$filename ==
'' )
$this->errMsg =
'the value of parameter (domain,filename) can not be empty!';
$this->setUrl( $this->getDom($domain), $filename );
$container =
$this->swift_conn->get_container($domain);
$this->errMsg =
$e->getMessage();
$result =
$container->delete_object($filename);
$this->errMsg =
$e->getMessage();
* - expires: 浏览器缓存超时,设置规则和domain expires的规则一致
* - encoding: 设置通过Web直接访问文件时,Header中的Content-Encoding。
* - type: 设置通过Web直接访问文件时,Header中的Content-Type。
* - private: 设置文件为私有,则文件不可被下载。
* $stor = new SaeStorage();
* $attr = array('expires' => '1 y');
* $ret = $stor->setFileAttr("test", "test.txt", $attr);
* var_dump($stor->errno(), $stor->errmsg());
* @param string $filename 文件名
* @param array $attr 文件属性。格式:array('attr0'=>'value0', 'attr1'=>'value1', ......);
public function setFileAttr( $domain, $filename, $attr =
array() )
$domain =
$this->parseDomain(trim($domain));
$filename =
$this->formatFilename($filename);
if ( $domain ==
'' ||
$filename ==
'' ) {
$this->errMsg =
'the value of parameter domain,filename can not be empty!';
$parseAttr =
$this->parseFileAttr($attr);
if ($parseAttr ==
false) {
$this->errMsg =
'the value of parameter attr must be an array, and can not be empty!';
$container =
$this->swift_conn->get_container($domain);
$this->errMsg =
$e->getMessage();
$object =
$container->get_object($filename);
$this->errMsg =
$e->getMessage();
$object->metadata =
$attr;
$result =
$object->sync_metadata();
$this->errMsg =
$e->getMessage();
* - expires 格式:[modified] TIME_DELTA,例如modified 1y或者1y,modified关键字用于指定expire时间相对于文件的修改时间。默认expire时间是相对于access time。如果TIME_DELTA为负, Cache-Control header会被设置为no-cache。
* - TIME_DELTA,TIME_DELTA是一个表示时间的字符串,例如: 1y3M 48d 5s
* - expires_type 格式:TYPE [modified] TIME_DELTA,TYPE为文件的mimetype,例如text/html, text/plain, image/gif。多条expires-type规则之间以 , 隔开。例如:text/html 48h,image/png modified 1y
* - allowReferer: 根据Referer防盗链
* - 404Redirect: 404跳转页面,只能是本应用页面,或本应用Storage中文件。例如http://appname.sinaapp.com/404.html或http://appname-domain.stor.sinaapp.com/404.png
* - tag: Domain简介。格式:array('tag1', 'tag2')
* $allowReferer = array();
* $allowReferer['hosts'][] = '*.elmerzhang.com'; // 允许访问的来源域名,千万不要带 http://。支持通配符*和?
* $allowReferer['hosts'][] = 'elmer.sinaapp.com';
* $allowReferer['hosts'][] = '?.elmer.sinaapp.com';
* $allowReferer['redirect'] = 'http://elmer.sinaapp.com/'; // 盗链时跳转到的地址,仅允许跳转到本APP的页面,且不可使用独立域名。如果不设置或者设置错误,则直接拒绝访问。
* //$allowReferer = false; // 如果要关闭一个Domain的防盗链功能,直接将allowReferer设置为false即可
* $stor = new SaeStorage();
* $attr = array('expires'=>$expires, 'allowReferer'=>$allowReferer);
* $ret = $stor->setDomainAttr("test", $attr);
* var_dump($stor->errno(), $stor->errmsg());
* @param array $attr Domain属性。格式:array('attr0'=>'value0', 'attr1'=>'value1', ......);
$domain =
$this->parseDomain(trim($domain));
$this->errMsg =
'The value of parameter domain can not be empty!';
$parseAttr =
$this->parseDomainAttr($attr);
if ($parseAttr ==
false) {
$this->errMsg =
'The value of parameter attr must be an array, and can not be empty!';
$container =
$this->swift_conn->get_container($domain);
$this->errMsg =
$e->getMessage();
$container->metadata =
$attr;
$result =
$container->sync_metadata();
$this->errMsg =
$e->getMessage();
$domain =
$this->parseDomain(trim($domain));
$this->errMsg =
'The value of parameter \'$domain\' can not be empty!';
$info =
$this->swift_conn->get_container($domain);
$this->errMsg =
$e->getMessage();
$info_array =
$this->std_class_object_to_array($info);
return $info_array['bytes_used'];
* @param $attr=array('private'=>false
public function createDomain( $domain=
'', $attr =
array('private'=>
false) )
return array( 'errno'=>-
102, 'errmsg'=>
'Domain length invalid(5,100)!domain('.
$domain.
')' );
if ( Empty( $domain ) ) {
$this->errMsg =
'The value of parameter \'domain\' can not be empty!';
$domain_explode =
explode("-", $domain);
if (count($domain_explode) !=
2) {
$this->errMsg =
'The value of parameter \'domain\' is not legit!';
$domain =
$domain_explode[1];
$this->errMsg =
sprintf("Set domain attr failed, %s", $e->getMessage());
$this->errMsg =
sprintf("Create domain failed, %s", $e->getMessage());
$ret =
$this->std_class_object_to_array($ret);
foreach ($ret as $small) {
$retnew[] =
$this->appName.
'-'.
$small['name'];
$this->errMsg =
$e->getMessage();
$this->errMsg =
'The value of parameter \'domain\' can not be empty!';
$domain_explode =
explode("-", $domain);
if (count($domain_explode) !=
2) {
$this->errMsg =
'The value of parameter \'domain\' is not legit!';
$domain =
$domain_explode[1];
$info_array =
$this->std_class_object_to_array($ret);
'expires'=>
$info_array['metadata']['X-Sws-Container-Meta-Expires'],
'expires_type'=>
$info_array['metadata']['X-Sws-Container-Meta-Expires-Type'],
'fileNum'=>
$info_array['object_count'],
'tag'=>
json_decode($info_array['metadata']['X-Sws-Container-Meta-Tags'],true),
'dataSize'=>(int)
$info_array['bytes_used'],
if ( isset
( $info_array['read'] ) ) {
$rrules =
explode(',', $info_array['read']);
$retmsg['allowReferer'] =
array();
$retmsg['allowReferer']['hosts'] =
array();
foreach ( $rrules as $rrule ) {
if ( substr($rrule, 0, 3) ==
'.r:' ) {
$retmsg['allowReferer']['hosts'][] =
substr($rrule, 3);
} elseif ( substr($rrule, 0, 4) ==
'.rd:' ) {
$retmsg['allowReferer']['redirect'] =
substr($rrule, 4);
if ( !$retmsg['allowReferer']['hosts'] ) {
$retmsg['private'] =
true;
$retmsg['private'] =
false;
$retmsg['private'] =
true;
$this->errMsg =
$e->getMessage();
public function deleteDomain( $domain , $force =
0 )
if ( empty( $domain ) ) {
$this->errMsg =
'The value of parameter \'domain\' can not be empty!';
$domain_explode =
explode("-", $domain);
if (count($domain_explode) !=
2) {
$this->errMsg =
'The value of parameter \'domain\' is not legit!';
$domain =
$domain_explode[1];
foreach ($files as $file) {
$this->delete($domain, $file);
$this->errMsg =
$e->getMessage();
public function runFile( $domain, $filename)
$this->errMsg =
'this function is discarded';
protected function getDom($domain, $concat =
true) {
if( strpos($domain, '-') ===
false ) {
$domain =
$this->appName .
'-'.
$domain;
if ( ( $pos =
strpos($domain, '-') ) !==
false ) {
$domain =
substr($domain, $pos +
1);
* @param string $filename
private function formatFilename($filename)
$filename =
trim($filename);
$encodings =
array( 'UTF-8', 'GBK', 'BIG5' );
$charset =
mb_detect_encoding( $filename , $encodings);
if ( $charset !=
'UTF-8' ) {
$filename =
mb_convert_encoding( $filename, "UTF-8", $charset);
$filename =
ltrim($filename, '/');
protected function parseDomainAttr($attr)
if ( !is_array( $attr ) ||
empty( $attr ) ) {
foreach ( $attr as $k =>
$a ) {
$parseAttr['404Redirect'] =
trim($a);
$parseAttr['private'] =
$a ?
true :
false;
$parseAttr['expires'] =
$a;
$parseAttr['expires_type'] =
$a;
if ( isset
($a['hosts']) &&
is_array($a['hosts']) &&
!empty($a['hosts']) ) {
$parseAttr['allowReferer'] =
array();
$parseAttr['allowReferer']['hosts'] =
$a['hosts'];
if ( isset
($a['redirect']) &&
is_string($a['redirect']) ) {
$parseAttr['allowReferer']['redirect'] =
$a['redirect'];
$parseAttr['allowReferer']['host'] =
false;
$parseAttr['tag'] =
array();
$parseAttr['tag'][] =
$v;
protected function parseFileAttr($attr)
if ( !is_array( $attr ) ||
empty( $attr ) ) {
foreach ( $attr as $k =>
$a ) {
$parseAttr['expires'] =
$a;
$parseAttr['encoding'] =
$a;
$parseAttr['private'] =
intval($a);
public function parseDomain( $domain )
list
($account, $container) =
explode('-', $domain);
protected function std_class_object_to_array($stdclassobject)
foreach ($_array as $key =>
$value) {
$value =
(is_array($value) ||
is_object($value)) ?
$this->std_class_object_to_array($value) :
$value;
Documentation generated on Wed, 03 Sep 2014 10:14:57 +0800 by phpDocumentor 1.4.3