From 2e7257b7b29011ab985bb9c0553b6d72d2a10e50 Mon Sep 17 00:00:00 2001
From: droomo
Date: Wed, 30 Sep 2015 03:26:19 +0800
Subject: [PATCH] first commit
---
AliOssSdk/alioss.class.php | 3 +
AliOssSdk/conf.inc.php | 13 +
AliOssSdk/docs/oss-php-sdk.md | 2140 +++++++++++++++++
AliOssSdk/lang/zh.inc.php | 99 +
AliOssSdk/lib/requestcore/LICENSE | 25 +
AliOssSdk/lib/requestcore/README.md | 15 +
.../lib/requestcore/requestcore.class.php | 1030 ++++++++
AliOssSdk/sdk.class.php | 2104 ++++++++++++++++
AliOssSdk/thirdparty/xml2array.class.php | 139 ++
AliOssSdk/util/mimetypes.class.php | 240 ++
AliOssSdk/util/oss_util.class.php | 434 ++++
Plugin.php | 586 +++++
12 files changed, 6828 insertions(+)
create mode 100644 AliOssSdk/alioss.class.php
create mode 100644 AliOssSdk/conf.inc.php
create mode 100644 AliOssSdk/docs/oss-php-sdk.md
create mode 100644 AliOssSdk/lang/zh.inc.php
create mode 100644 AliOssSdk/lib/requestcore/LICENSE
create mode 100644 AliOssSdk/lib/requestcore/README.md
create mode 100644 AliOssSdk/lib/requestcore/requestcore.class.php
create mode 100644 AliOssSdk/sdk.class.php
create mode 100644 AliOssSdk/thirdparty/xml2array.class.php
create mode 100644 AliOssSdk/util/mimetypes.class.php
create mode 100644 AliOssSdk/util/oss_util.class.php
create mode 100644 Plugin.php
diff --git a/AliOssSdk/alioss.class.php b/AliOssSdk/alioss.class.php
new file mode 100644
index 0000000..9428f14
--- /dev/null
+++ b/AliOssSdk/alioss.class.php
@@ -0,0 +1,3 @@
+set_enable_domain_style(true);
+
+ `
+
+* 使用sts方式初始化ALIOSS
+ * 如果是移动端的开发者,需要使用sts服务,只需要在初始化的时候调用sts的api生成临时的accessId,accessKey,以及securityToken即可。
+
+ `
+ $access_id = "调用sts接口得到的临时access_id";
+ $access_key = "调用sts接口得到的临时access_key";
+ $end_point = "操作集群的endpoint";
+ $security_token = "调用sts接口得到的临时security_token";
+ $client = ALIOSS($access_id,$access_key,$end_point,$security_token);
+
+ `
+
+## Bucket相关操作
+* 获取bucket列表
+ * 示例代码
+
+ `
+ $options = null;
+ $response = $client->list_bucket($options);
+
+ `
+ * 参数说明
+
+ `
+ $options 可选参数,无需设置
+
+ `
+ * 响应结果
+ 、
+ 将结果Response转换成array得到,下同
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Wed, 01 Jul 2015 09:21:15 GMT
+ [content-type] => application/xml
+ [content-length] => 6266
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5593B10B58DB3AB752154A62
+ )
+ [body] => Array(
+ [ListAllMyBucketsResult] => Array(
+ [Owner] => Array (
+ [ID] => 128257
+ [DisplayName] => 128257
+ )
+ [Buckets] => Array(
+ [Bucket] => Array(
+ [0] => Array(
+ [Location] => oss-cn-hangzhou
+ [Name] => 33331111
+ [CreationDate] => 2014-08-27T03:04:20.000Z
+ )
+ [1] => Array (
+ [Location] => oss-cn-qingdao
+ [Name] => a-00000000000000000001
+ [CreationDate] => 2015-05-22T05:30:40.000Z
+ )
+
+ )
+
+ )
+
+ )
+
+ )
+
+ )
+ 、
+* 创建bucket
+ * 示例代码
+
+ `
+ $bucket_name = "bucket name";
+ $acl = ALIOSS::OSS_ACL_TYPE_PRIVATE;
+ $options = null;
+ $response = $client->create_bucket($bucket_name,$acl,$options);
+
+ `
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,需要符合bucket命名规范
+ $acl 必选参数,只能从private,public-read,public-read-write中任选一个,分别和以下常量映射
+ ALIOSS::OSS_ACL_TYPE_PRIVATE,
+ ALIOSS::OSS_ACL_TYPE_PUBLIC_READ,
+ ALIOSS::OSS_ACL_TYPE_PUBLIC_READ_WRITE
+ $options 可选参数,无需设置
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Wed, 01 Jul 2015 09:55:18 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5593B906031C87E546154CC1
+ )
+
+ [body] =>
+ )
+
+ `
+
+* 删除bucket
+ * 示例代码
+
+ `
+
+ $bucket_name = "bucket name";
+ $options = null;
+ $response = $client->delete_bucket($bucket_name,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,需要符合bucket命名规范
+ $options 可选参数,无需设置
+
+ `
+ * 响应结果
+
+ `
+
+ 将结果Response转换成array得到,下同
+ Array(
+ [status] => 204
+ [header] => Array(
+ [date] => Wed, 01 Jul 2015 10:08:45 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5593BC2D58DB3AB752155156
+ )
+
+ [body] =>
+ )
+
+ `
+* 获取bucket Acl
+ * 示例代码
+
+ `
+
+ $bucket_name = "bucket name";
+ $options = null;
+ $response = $client->get_bucket_acl($bucket_name,$options);
+
+
+ `
+ * 参数说明
+
+ `
+ $bucket_name 必选参数,需要符合bucket命名规范
+ $options 可选参数,无需设置
+
+ `
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Wed, 01 Jul 2015 10:17:41 GMT
+ [content-type] => application/xml
+ [content-length] => 239
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5593BE45031C87E54615500F
+ )
+
+ [body] => Array(
+ [AccessControlPolicy] => Array(
+ [Owner] => Array(
+ [ID] => 128257
+ [DisplayName] => 128257
+ )
+
+ [AccessControlList] => Array(
+ [Grant] => public-read
+ )
+ )
+ )
+ )
+
+ `
+
+* 设置bucket Acl
+ * 示例代码
+
+ `
+ $bucket_name = "bucket name";
+ $options = null;
+ $response = $client->set_bucket_acl($bucket_name,$options);
+ `
+
+ * 参数说明
+
+ `
+ $bucket_name 必选参数,需要符合bucket命名规范
+ $options 可选参数,无需设置
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Wed, 01 Jul 2015 11:08:31 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5593CA2F031C87E5461557B5
+ )
+
+ [body] =>
+ )
+ `
+
+## Object相关操作
+* 获取Object列表
+ * 示例代码
+
+ `
+ $bucket_name = 'bucket name';
+ $options = array(
+ 'delimiter' => '/',
+ 'prefix' => '',
+ 'max-keys' => 5,
+ 'marker' => '',
+ );
+
+ $response = $client->list_object($$bucket_name,$options);
+
+ `
+
+
+ * 参数说明
+
+
+ `
+
+ $bucket_name 必选参数,需要符合bucket命名规范
+ $options 可选参数,其中的参数说明如下
+ delimiter 是一个用于对Object名字进行分组的字符。所有名字包含指定的前缀且第一次出现delimiter
+ 字符之间的object作为一组元素——CommonPrefixes。
+ prefix 限定返回的object key必须以prefix作为前缀。注意使用prefix查询时,返回的key中
+ 仍会包含prefix
+ max-keys 限定此次返回object的最大数,如果不设定,默认为100,max-keys取值不能大于1000
+ marker 设定结果从marker之后按字母排序的第一个开始返回
+
+ `
+
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 07:59:32 GMT
+ [content-type] => application/xml
+ [content-length] => 1466
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594EF64031C87E546160F24
+ )
+
+ [body] => Array(
+ [ListBucketResult] => Array(
+ [Name] => common-bucket
+ [Prefix] =>
+ [Marker] =>
+ [MaxKeys] => 5
+ [Delimiter] => /
+ [IsTruncated] => true
+ [NextMarker] => metro_driver.dll
+ [Contents] => Array(
+ [0] => Array(
+ [Key] => chrome_elf.dll
+ [LastModified] => 2015-07-01T03:44:58.000Z
+ [ETag] => "78CE940FD1CCDF6F743EE1A9AED8AAD8"
+ [Type] => Normal
+ [Size] => 133960
+ [StorageClass] => Standard
+ [Owner] => Array(
+ [ID] => 128257
+ [DisplayName] => 128257
+ )
+ )
+
+ [1] => Array(
+ [Key] => delegate_execute.exe
+ [LastModified] => 2015-06-29T09:18:41.000Z
+ [ETag] => "37C49C4E0EC4E0D96B6EBBA2190E8824"
+ [Type] => Normal
+ [Size] => 692040
+ [StorageClass] => Standard
+ [Owner] => Array(
+ [ID] => 128257
+ [DisplayName] => 128257
+ )
+ )
+ }
+
+ [CommonPrefixes] => Array(
+ [0] => Array(
+ [Prefix] => common-folder/
+ )
+
+ [1] => Array(
+ [Prefix] => common-folder2/
+ )
+ )
+ )
+ )
+ )
+
+ `
+
+
+* 创建虚拟文件夹
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $dir_name = 'directory name';
+ $options = null;
+ $response = $client->create_object_dir($bucket_name,$dir_name,$options);
+
+ `
+
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $dir_name 必选参数,必须符合object命名规范
+ $options 可选参数,对于虚拟文件夹而言,无需设置一些header头
+
+
+ `
+
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 08:10:16 GMT
+ [content-length] => 0
+ [connection] => close
+ [etag] => "D41D8CD98F00B204E9800998ECF8427E"
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594F1E8031C87E5461610B9
+ )
+
+ [body] =>
+ )
+
+ `
+
+
+* 上传文件(直接指定内容)
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $object_name = 'object name';
+ $content = 'object content';
+ $options = array(
+ 'content' => $content,
+ 'length' => strlen($content),
+ ALIOSS::OSS_HEADERS => array(
+ 'Expires' => 'Fri, 28 Feb 2012 05:38:42 GMT',
+ 'Cache-Control' => 'no-cache',
+ 'Content-Disposition' => 'attachment;filename=oss_download.log',
+ 'Content-Encoding' => 'utf-8',
+ 'Content-Language' => 'zh-CN',
+ 'x-oss-server-side-encryption' => 'AES256',
+ ),
+ );
+ $response = $obj->upload_file_by_content($bucket_name,$object_name,$options);
+
+ `
+
+ * 参数说明
+
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $object_name 必选参数,必须符合object命名规范
+ $options 必选参数,该参内指定上传所需要的各种信息,具体各参数说明如下
+ content 上传object的内容
+ length 上传object的大小
+ ALIOSS::OSS_HEADERS 该参数可选,如果指定,则可以设置该object的一些meta信息,可以设置的头信息如下:
+ Expires 过期时间(milliseconds)
+ Cache-Control 指定该Object被下载时的网页的缓存行为
+ Content-Disposition 指定该Object被下载时的名称
+ Content-Encoding 指定该Object被下载时的内容编码格式
+ Content-Language 指定object被下载时候的语言
+ x-oss-server-side-encryption 指定oss创建object时的服务器端加密编码算法
+
+ `
+
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 08:24:11 GMT
+ [content-length] => 0
+ [connection] => close
+ [etag] => "9BA9EF6DDFBE14916FA2D3337B427774"
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594F52B031C87E5461612D1
+ )
+
+ [body] =>
+ )
+
+ `
+
+* 上传文件(指定上传路径)
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $object_name = 'object name';
+ $file_path = "upload file path";
+ $options = array(
+ ALIOSS::OSS_HEADERS => array(
+ 'Expires' => 'Fri, 28 Feb 2012 05:38:42 GMT',
+ 'Cache-Control' => 'no-cache',
+ 'Content-Disposition' => 'attachment;filename=oss_download.gz',
+ 'Content-Encoding' => 'utf-8',
+ 'Content-Language' => 'zh-CN',
+ 'x-oss-server-side-encryption' => 'AES256',
+
+ ),
+ );
+ $response = $obj->upload_file_by_file($bucket,$object,$file_path,$upload_file_options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $object_name 必选参数,必须符合object命名规范
+ $file_path 必选参数,文件所在的路径
+ $options 必选参数,该参内指定上传所需要的各种信息,具体各参数说明如下
+ content 上传object的内容
+ length 上传object的大小
+ ALIOSS::OSS_HEADERS 该参数可选,如果指定,则可以设置该object的一些meta信息,可以设置的头信息如下:
+ Expires 过期时间(milliseconds)
+ Cache-Control 指定该Object被下载时的网页的缓存行为
+ Content-Disposition 指定该Object被下载时的名称
+ Content-Encoding 指定该Object被下载时的内容编码格式
+ Content-Language 指定object被下载时候的语言
+ x-oss-server-side-encryption 指定oss创建object时的服务器端加密编码算法
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 08:41:10 GMT
+ [content-length] => 0
+ [connection] => close
+ [etag] => "4B12FF064A3BBFE0AE5A1314E77FF0DF"
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594F91358DB3AB7521617CA
+ )
+
+ [body] =>
+ )
+
+ `
+
+
+* 拷贝Object
+ * 示例代码
+
+ `
+
+ $from_bucket = 'copy from bucket';
+ $from_object = 'copy from object';
+ $to_bucket = 'copy to bucket';
+ $to_object = 'copy to object';
+ $options = array(
+ ALIOSS::OSS_HEADERS => array(
+ 'x-oss-copy-source-if-match' => 'E024E425254F1EEDB237F69F854CE883',
+ 'x-oss-copy-source-if-none-match' => 'Thu, 18 Jun 2015 08:50:31 GMT',
+ 'x-oss-copy-source-if-unmodified-since' => 'Thu, 18 Jun 2015 08:50:31 GMT',
+ 'x-oss-copy-source-if-modified-since' => 'Thu, 18 Jun 2015 09:50:31 GMT',
+ 'x-oss-metadata-directive' => 'COPY',
+ 'x-oss-server-side-encryption' => 'AES256'
+ )
+ );
+
+ $response = $obj->copy_object($from_bucket,$from_object,$to_bucket,$to_object,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $from_bucket 必选参数,源bucket,必须符合bucket命名规范
+ $from_object 必选参数,源object,必须符合object命名规范
+ $to_bucket 必选参数,目标bucket,必须符合bucket命名规范
+ $to_object 必选参数,目标object,必须符合object命名规范
+ $options 可选参数,如果需要设置,可以设置 ALIOSS::OSS_HEADERS 头参数,参数有如下的几个选项
+ x-oss-copy-source-if-match 如果源Object的ETAG值和用户提供的ETAG相等,则执行拷贝操作;
+ 否则返回412 HTTP错误码(预处理失败)
+ x-oss-copy-source-if-none-match 如果源Object自从用户指定的时间以后就没有被修改过,则执行拷贝操作;
+ 否则返回412 HTTP错误码(预处理失败)
+ x-oss-copy-source-if-unmodified-since 如果传入参数中的时间等于或者晚于文件实际修改时间,则正常传输文件,
+ 并返回200 OK;否则返回412 precondition failed错误
+ x-oss-copy-source-if-modified-since 如果源Object自从用户指定的时间以后被修改过,则执行拷贝操作;
+ 否则返回412 HTTP错误码(预处理失败)
+ x-oss-metadata-directive 有效值为COPY和REPLACE。如果该值设为COPY,则新的Object的meta都从源Object复制过来;
+ 如果设为REPLACE,则忽视所有源Object的meta值,而采用用户这次请求中指定的meta值;其他值则返回400 HTTP错误码。
+ 注意该值为COPY时,源Object的x-oss-server-side-encryption的meta值不会进行拷贝;默认值为COPY
+ x-oss-server-side-encryption 指定oss创建目标object时的服务器端熵编码加密算法,目前仅支持AES256
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [content-type] => application/xml
+ [content-length] => 184
+ [connection] => close
+ [date] => Thu, 02 Jul 2015 09:26:28 GMT
+ [etag] => "E024E425254F1EEDB237F69F854CE883"
+ [server] => AliyunOSS
+ [x-oss-request-id] => 559503C458DB3AB752161E83
+ [x-oss-server-side-encryption] => AES256
+ )
+
+ [body] => Array(
+ [CopyObjectResult] => Array(
+ [LastModified] => 2015-07-02T09:26:28.000Z
+ [ETag] => "E024E425254F1EEDB237F69F854CE883"
+ )
+ )
+ )
+
+ `
+
+
+* 获取Object MetaData
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $object_name = 'object name';
+ $options = null;
+ $response = $client->get_object_meta($bucket_name,$object_name,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $object_name 必选参数,必须符合object命名规范
+ $options 可选参数,无需设置
+
+ `
+
+ * 响应结果
+
+ `
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 09:03:40 GMT
+ [content-type] => plain/text
+ [content-length] => 10
+ [connection] => close
+ [accept-ranges] => bytes
+ [cache-control] => no-cache
+ [content-disposition] => attachment;filename=oss_download.log
+ [content-encoding] => utf-8
+ [content-language] => zh-CN
+ [etag] => "9BA9EF6DDFBE14916FA2D3337B427774"
+ [expires] => Fri, 28 Feb 2012 05:38:42 GMT
+ [last-modified] => Thu, 02 Jul 2015 08:38:10 GMT
+ [server] => AliyunOSS
+ [x-oss-object-type] => Normal
+ [x-oss-request-id] => 5594FE6C031C87E5461618B6
+ [x-oss-server-side-encryption] => AES256
+ )
+
+ [body] =>
+ )
+
+ `
+
+* 删除单个Object
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $object_name = 'object name';
+ $options = null;
+ $response = $client->delete_object($bucket_name,$object_name,$options);
+
+ `
+
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $object_name 必选参数,必须符合object命名规范
+ $options 可选参数,无需设置
+
+ `
+
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 204
+ [header] => Array(
+ [content-length] => 0
+ [connection] => close
+ [date] => Thu, 02 Jul 2015 10:01:00 GMT
+ [server] => AliyunOSS
+ [x-oss-request-id] => 55950BDC58DB3AB75216239D
+ )
+
+ [body] =>
+ )
+
+
+ `
+
+
+* 删除多个Object
+ * 示例代码
+
+
+ `
+
+ $bucket_name = 'bucket name';
+ $objects = array(
+ 'delete object 1',
+ 'delete object 2',
+ ...
+ );
+
+ $options = array(
+ 'quiet' => false,
+ );
+
+ $response = $client->delete_objects($bucket_name,$objects,$options);
+
+ `
+
+
+ * 参数说明
+
+ `
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $objects 必选参数,其中的object必须符合object命名规范
+ $options 可选参数,此处可以根据实际情况选择删除的两种模式,quite 参数可有true|false两种选择,
+ true OSS返回的消息体中只包含删除过程中出错的Object结果;如果所有删除都成功的话,则没有消息体。
+ false OSS返回的消息体中会包含每一个删除Object的结果
+
+ `
+
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [content-type] => application/xml
+ [content-length] => 188
+ [connection] => close
+ [date] => Thu, 02 Jul 2015 10:06:00 GMT
+ [server] => AliyunOSS
+ [x-oss-request-id] => 55950D0858DB3AB752162459
+ )
+
+ [body] => Array(
+ [DeleteResult] => Array(
+ [Deleted] => Array(
+ [0] => Array(
+ [Key] => delegate_execute.exe
+ )
+
+ [1] => Array(
+ [Key] => metro_driver.dll
+ )
+ )
+ )
+ )
+
+
+ `
+
+
+* 下载Object
+ * 示例代码
+
+ `
+
+ $bucket_name = 'download bucket';
+ $object_name = 'download object';
+
+ $options = array(
+ ALIOSS::OSS_FILE_DOWNLOAD => "download path",
+ ALIOSS::OSS_RANGE => '0-1',
+ );
+
+ $response = $client>get_object($bucket_name,$object_name,$options);
+
+ `
+
+ * 参数说明
+
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $object_name 必选参数,必须符合object命名规范
+ $options 必选参数,该参数中必须设置ALIOSS::OSS_FILE_DOWNLOAD,ALIOSS::OSS_RANGE可选,可以根据实际情况设置;
+ 如果不设置,默认会下载全部内容
+
+
+ `
+
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 206
+ [header] => Array(
+ )
+
+ [body] =>
+ )
+
+ `
+
+
+## MultipartUpload相关操作
+* 初始化 multipartUpload
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $object_name = 'object name';
+ $options = array(
+ ALIOSS::OSS_HEADERS => array(
+ 'Expires' => 'Fri, 28 Feb 2012 05:38:42 GMT',
+ 'Cache-Control' => 'no-cache',
+ 'Content-Disposition' => 'attachment;filename=oss_download.log',
+ 'Content-Encoding' => 'utf-8',
+ 'Content-Type' => 'plain/text',
+ 'Content-Language' => 'zh-CN',
+ 'x-oss-server-side-encryption' => 'AES256',
+ ),
+ );
+ $response = $client->initiate_multipart_upload($bucket_name,$object_name,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $object_name 必选参数,必须符合object命名规范
+ $options 必选参数,该参内指定上传所需要的各种信息,具体各参数说明如下
+ ALIOSS::OSS_HEADERS 该参数可选,如果指定,则可以设置该object的一些meta信息,可以设置的头信息如下:
+ Expires 过期时间(milliseconds)
+ Cache-Control 指定该Object被下载时的网页的缓存行为
+ Content-Disposition 指定该Object被下载时的名称
+ Content-Encoding 指定该Object被下载时的内容编码格式
+ 'Content-Type' => 'plain/text'指定Object响应时的MIME类型
+ Content-Language 指定object被下载时候的语言
+ x-oss-server-side-encryption 指定oss创建object时的服务器端加密编码算法
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [content-type] => application/xml
+ [content-length] => 234
+ [connection] => close
+ [date] => Thu, 02 Jul 2015 11:35:36 GMT
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5595220858DB3AB7521631B1
+ [x-oss-server-side-encryption] => AES256
+ )
+
+ [body] => Array(
+ [InitiateMultipartUploadResult] => Array(
+ [Bucket] => common-bucket
+ [Key] => multipart-upload-1435836936
+ [UploadId] => 154A34BD1FE24A90A025EB800AA392CC
+ )
+ )
+ )
+
+ `
+
+
+* 上传Part
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $object_name = 'object name';
+ $upload_id = 'upload id';
+ $options = array(
+ 'fileUpload' => 'upload path',
+ 'partNumber' => 1,
+ 'seekTo' => 1,
+ 'length' => 5242880,
+ );
+
+ $response = $client->upload_part($bucket_name,$object_name, $upload_id, $options);
+
+ `
+
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $object_name 必选参数,必须符合object命名规范
+ $upload_id 必选参数,上传part对应的multipart uploads Id
+ $options 必选参数,该参内指定上传所需要的各种信息,具体各参数说明如下
+ fileUpload 上传文件的路径
+ partNumber 上传part的序号
+ seekTo 读取上传文件的起始字节
+ length 切片大小
+
+ `
+
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [content-length] => 0
+ [connection] => close
+ [date] => Thu, 02 Jul 2015 11:35:36 GMT
+ [etag] => "3AE3AD480200A26738F10CBF2FFBE8B6"
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5595220858DB3AB7521631B3
+ [x-oss-server-side-encryption] => AES256
+ )
+
+ [body] =>
+ )
+
+ `
+
+
+* 拷贝Upload Part
+ * 示例代码
+
+ `
+
+ $from_bucket = 'copy from bucket';
+ $from_object = 'copy from object';
+ $to_bucket = 'copy to bucket';
+ $to_object = 'copy to object';
+ $part_number = 1;
+ $upload_id = 'copy to upload id';
+ $options = array(
+ 'start' => 0,
+ 'end' => 25000032,
+ );
+
+ $response = $client->copy_upload_part($from_bucket,$from_object,$to_bucket,$to_object,$part_number,$upload_id,$options);
+
+
+ `
+
+ * 参数说明
+
+ `
+
+ $from_bucket 必选参数,源bucket,必须符合bucket命名规范
+ $from_object 必选参数,源object,必须符合object命名规范
+ $to_bucket 必选参数,目标bucket,必须符合bucket命名规范
+ $to_object 必选参数,目标object,必须符合object命名规范
+ $part_number 必选参数,范围是1~10,000
+ $upload_id 必选参数,初始化multipartupload返回的uploadid
+ $options 可选参数,如果需要设置,可以设置isFullCopy,startRange,endRange和
+ ALIOSS::OSS_HEADERS 等参数,其中ALIOSS::OSS_HEADERS中可以设置的参数如下:
+ x-oss-copy-source-if-match 如果源Object的ETAG值和用户提供的ETAG相等,则执行拷贝操作;
+ 否则返回412 HTTP错误码(预处理失败)
+ x-oss-copy-source-if-none-match 如果源Object自从用户指定的时间以后就没有被修改过,则执行拷贝操作;
+ 否则返回412 HTTP错误码(预处理失败)
+ x-oss-copy-source-if-unmodified-since 如果传入参数中的时间等于或者晚于文件实际修改时间,则正常传输文件,
+ 并返回200 OK;否则返回412 precondition failed错误
+ x-oss-copy-source-if-modified-since 如果源Object自从用户指定的时间以后被修改过,则执行拷贝操作;
+ 否则返回412 HTTP错误码(预处理失败)
+ isFullCopy 是否启用全部拷贝,如果设置为true,则无需设置startRange和endRange
+ startRange 如果isFullCopy为false,该参数有效,指的是拷贝来源object的起始位置
+ endRange 如果isFullCopy为false,该参数有效,指的是拷贝开源object的终止位置
+
+ `
+
+ * 响应结果
+ `
+ 将结果Response转换成array得到,下同
+
+ Array
+ (
+ [success] => 1
+ [status] => 200
+ [header] => Array
+ (
+ [date] => Thu, 06 Aug 2015 18:13:59 GMT
+ [content-type] => application/xml
+ [content-length] => 180
+ [connection] => keep-alive
+ [content-range] => bytes 11304368-11534335/11534336
+ [etag] => "E95C28888F15B92B9C49C9ECEC53C958"
+ [server] => AliyunOSS
+ [x-oss-bucket-version] => 1438864637
+ [x-oss-request-id] => 55C3A3E79646C3C03F40EA5E
+ )
+
+ [body] => Array
+ (
+ [CopyPartResult] => Array
+ (
+ [LastModified] => 2015-08-06T18:13:59.000Z
+ [ETag] => "E95C28888F15B92B9C49C9ECEC53C958"
+ )
+
+ )
+
+ )
+ `
+* 获取Part列表
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $object_name = 'object name';
+ $upload_id = 'upload id';
+ $options = null;
+ $response = $client->list_parts($bucket_name,$object_name, $upload_id,$options);
+
+ `
+
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $object_name 必选参数,必须符合object命名规范
+ $upload_id 必选参数,上传part对应的multipart uploads Id
+ $options 可选参数,无需设置
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [content-type] => application/xml
+ [content-length] => 584
+ [connection] => close
+ [date] => Thu, 02 Jul 2015 11:35:40 GMT
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5595220C031C87E546162F44
+ )
+
+ [body] => Array(
+ [ListPartsResult] => Array(
+ [Bucket] => common-bucket
+ [Key] => multipart-upload-1435836813
+ [UploadId] => B4D4B89F8B064A3D835D83D7805B49F3
+ [StorageClass] => Standard
+ [PartNumberMarker] => 0
+ [NextPartNumberMarker] => 1
+ [MaxParts] => 1000
+ [IsTruncated] => false
+ [Part] => Array(
+ [PartNumber] => 1
+ [LastModified] => 2015-07-02T11:35:40.000Z
+ [ETag] => "3AE3AD480200A26738F10CBF2FFBE8B6"
+ [Size] => 5242880
+ )
+ )
+ )
+ )
+
+ `
+
+
+* 获取mulipartUpload列表
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $options = array(
+ 'delimiter' => '/',
+ 'max-uploads' => 2,
+ 'key-marker' => '',
+ 'prefix' => '',
+ 'upload-id-marker' => ''
+ );
+ $response = $client->list_multipart_uploads($bucket_name,$options);
+
+
+ `
+
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $options 可选参数,如果需要设置,可以设置如下参数
+ delimiter 是一个用于对Object名字进行分组的字符。所有名字包含指定的前缀且第一次出现delimiter字符之间的object作为一组元素——
+ CommonPrefixes max-uploads 限定此次返回Multipart Uploads事件的最大数目,如果不设定,默认为1000,max-keys取值不能大于1000
+ key-marker 与upload-id-marker参数一同使用来指定返回结果的起始位置。 l 如果upload-id-marker参数未设置,查询结果中包含:
+ 所有Object名字的字典序大于key-marker参数值的Multipart事件。 l 如果upload-id-marker参数被设置,查询结果中包含:
+ 所有Object名字的字典序大于key-marker参数值的Multipart事件和Object名字等于key-marker参数值,但是Upload ID比upload-id-marker
+ 参数值大的Multipart Uploads事件
+ prefix 限定返回的object key必须以prefix作为前缀。注意使用prefix查询时,返回的key中仍会包含prefix
+ upload-id-marker 与key-marker参数一同使用来指定返回结果的起始位置。 l 如果key-marker参数未设置,则OSS忽略upload-id-marker参数。
+ 如果key-marker参数被设置,查询结果中包含:所有Object名字的字典序大于key-marker参数值的Multipart事件和Object名字等于key-marker
+ 参数值,但是Upload ID比upload-id-marker参数值大的Multipart Uploads事件
+
+ `
+
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [content-type] => application/xml
+ [content-length] => 876
+ [connection] => close
+ [date] => Thu, 02 Jul 2015 12:01:50 GMT
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5595282E031C87E546163301
+ )
+
+ [body] => Array(
+ [ListMultipartUploadsResult] => Array(
+ [Bucket] => common-bucket
+ [KeyMarker] =>
+ [UploadIdMarker] =>
+ [NextKeyMarker] => multipart-upload-1435835648
+ [NextUploadIdMarker] => 5C79DDEC71DE478AA4AD9E9AA8BFE6DE
+ [Delimiter] => /
+ [Prefix] =>
+ [MaxUploads] => 2
+ [IsTruncated] => true
+ [Upload] => Array(
+ [0] => Array(
+ [Key] => multipart-upload-1435835395
+ [UploadId] => 799C914C0EC3448BAC126849A1B1D6D0
+ [StorageClass] => Standard
+ [Initiated] => 2015-07-02T11:09:55.000Z
+ )
+
+ [1] => Array(
+ [Key] => multipart-upload-1435835648
+ [UploadId] => 5C79DDEC71DE478AA4AD9E9AA8BFE6DE
+ [StorageClass] => Standard
+ [Initiated] => 2015-07-02T11:14:08.000Z
+ )
+ )
+ )
+ )
+ )
+
+ `
+
+
+* 终止multipartUpload
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $object_name = 'object name';
+ $upload_id = 'upload id';
+ $options = null;
+ $response = $client->abort_multipart_upload($bucket_name,$object_name,$upload_id,$options);
+
+
+ `
+
+
+ * 参数说明
+ *
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $object_name 必选参数,必须符合object命名规范
+ $upload_id 必选参数,上传part对应的multipart uploads Id
+ $options 可选参数,无需设置
+
+ `
+
+
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 204
+ [header] => Array(
+ [content-length] => 0
+ [connection] => close
+ [date] => Thu, 02 Jul 2015 11:53:52 GMT
+ [server] => AliyunOSS
+ [x-oss-request-id] => 55952650031C87E5461631E7
+ )
+
+ [body] =>
+ )
+
+ `
+
+
+* 完成multipartUpload
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $object_name = 'object name';
+ $upload_id = 'upload id';
+
+ $upload_parts = array();
+ $upload_parts[] = array(
+ 'PartNumber' => 1,
+ 'ETag' => '3AE3AD480200A26738F10CBF2FFBE8B6'
+ );
+ $options = null;
+ $response = $client->complete_multipart_upload($bucket_name,$object_name,$upload_id,$upload_parts,$options);
+
+ `
+
+ * 参数说明
+
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $object_name 必选参数,必须符合object命名规范
+ $upload_id 必选参数,上传part对应的multipart uploads Id
+ $upload_parts 包含part的数组,其中必须包含PartNumber和Etag
+ $options 可选参数,无需设置
+
+ `
+
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [content-type] => application/xml
+ [content-length] => 331
+ [connection] => close
+ [date] => Thu, 02 Jul 2015 11:35:40 GMT
+ [etag] => "003B6AEB546001A97D838E411025239A-1"
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5595220C031C87E546162F45
+ [x-oss-server-side-encryption] => AES256
+ )
+
+ [body] => Array(
+ [CompleteMultipartUploadResult] => Array(
+ [Location] => http://common-bucket.oss-cn-shanghai.aliyuncs.com/multipart-upload-1435836813
+ [Bucket] => common-bucket
+ [Key] => multipart-upload-1435836813
+ [ETag] => "003B6AEB546001A97D838E411025239A-1"
+ )
+ )
+ )
+
+ `
+## 生命周期管理(LifeCycle)
+* 创建Lifecycle规则
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $lifecycle = "
+
+
+ DaysRule
+ days/
+ Enabled
+
+ 1
+
+
+ " ;
+ $options = null;
+ $response = $client->set_bucket_lifecycle($bucket_name,$lifecycle,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $lifecycle 必选参数,lifecycle规则,具体请xml元素说明请参阅oss api文档:
+ http://docs.aliyun.com/?spm=5176.383663.9.2.1hkILe#/pub/oss/api-reference/bucket&PutBucketLifecycle
+ $options 可选参数,无需设置
+
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 06:32:57 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594DB19031C87E5461601D1
+ )
+
+ [body] =>
+ )
+
+ `
+
+* 获取lifeCycle规则
+ * 示例代码
+
+ `
+
+ $bucket_name = "bucket name";
+ $options = null;
+ $response = $client->get_bucket_lifecycle($bucket_name,$options);
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $options 可选参数,无需设置
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 06:32:57 GMT
+ [content-type] => application/xml
+ [content-length] => 243
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594DB1958DB3AB75216045C
+ )
+
+ [body] => Array(
+ [LifecycleConfiguration] => Array(
+ [Rule] => Array(
+ [ID] => DaysRule
+ [Prefix] => days/
+ [Status] => Enabled
+ [Expiration] => Array(
+ [Days] => 1
+ )
+ )
+ )
+ )
+ )
+
+ `
+
+* 删除lifeCycle规则
+ * 示例代码
+
+ `
+
+ $bucket_name = "bucket name";
+ $options = null;
+ $response = $client->delete_bucket_lifecycle($bucket_name,$options);
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $options 可选参数,无需设置
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 204
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 06:32:58 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594DB1A58DB3AB75216045D
+ )
+
+ [body] =>
+ )
+
+ `
+
+## 跨域资源管理(CORS)
+* 创建CORS规则
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+
+ $cors_rule = array();
+
+ $cors_rule[ALIOSS::OSS_CORS_ALLOWED_HEADER]=array("x-oss-test");
+ $cors_rule[ALIOSS::OSS_CORS_ALLOWED_METHOD]=array("GET");
+ $cors_rule[ALIOSS::OSS_CORS_ALLOWED_ORIGIN]=array("http://www.b.com");
+ $cors_rule[ALIOSS::OSS_CORS_EXPOSE_HEADER]=array("x-oss-test1");
+ $cors_rule[ALIOSS::OSS_CORS_MAX_AGE_SECONDS] = 10;
+
+ $cors_rules=array($cors_rule);
+
+ $options = null;
+ $response = $obj->set_bucket_cors($bucket_name, $cors_rules,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $cors_rules 定义一个cors规则数组,每条规则中需要包含以下元素
+ ALIOSS::OSS_CORS_ALLOWED_ORIGIN 必选,指定允许的跨域请求的来源,每条规则最多能有一个"*"符号
+ ALIOSS::OSS_CORS_ALLOWED_METHOD 必选,指定允许的跨域请求方法,仅能从GET,PUT,POST,DELETE,HEAD中选择一个或多个
+ ALIOSS::OSS_CORS_ALLOWED_HEADER 可选,控制在OPTIONS预取指令中Access-Control-Request-Headers头中指定的header是否允许。
+ 在Access-Control-Request-Headers中指定的每个header都必须在AllowedHeader中有一条对应的项。允许使用最多一个“*”通配符
+ ALIOSS::OSS_CORS_EXPOSE_HEADER 可选,指定允许用户从应用程序中访问的响应头(例如一个Javascript的XMLHttpRequest对象。)
+ 不允许使用“*”通配符。
+ ALIOSS::OSS_CORS_MAX_AGE_SECONDS 可选,指定浏览器对特定资源的预取(OPTIONS)请求返回结果的缓存时间,单位为秒。
+ 一个CORSRule里面最多允许出现一个。
+
+ $options 可选参数,无需设置
+
+ `
+
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 07:03:29 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594E241031C87E546160697
+ )
+
+ [body] =>
+ )
+
+
+ `
+
+* 获取CORS规则
+ * 示例代码
+
+ `
+
+ $bucket = 'bucket name';
+ $options = null;
+ $response = $client->get_bucket_cors($bucket_name,$options);
+
+ `
+
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必须参数,必须符合bucket命名规范
+ $options 可选参数,无需设置
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 07:03:39 GMT
+ [content-type] => application/xml
+ [content-length] => 327
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594E24B58DB3AB752160920
+ )
+
+ [body] => Array(
+ [CORSConfiguration] => Array(
+ [CORSRule] => Array(
+ [AllowedOrigin] => http://www.b.com
+ [AllowedMethod] => GET
+ [AllowedHeader] => x-oss-test
+ [ExposeHeader] => x-oss-test1
+ [MaxAgeSeconds] => 10
+ )
+ )
+ )
+ )
+
+ `
+
+* 评估是否允许跨域请求
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $object_name ='object name';
+ $origin = 'http://www.b.com';
+ $request_method = ALIOSS::OSS_HTTP_GET;
+ $request_headers = 'x-oss-test';
+ $options = null;
+
+ $response = $obj->options_object($bucket_name, $object_name, $origin, $request_method, $request_headers,$options);
+
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必须参数,必须符合bucket命名规范
+ $object_name 必选参数,必须符合object命名规范
+ $origin 必选参数,请求来源域,用来标示跨域请求
+ $request_method 必选参数,表示在实际请求中将会用到的方法
+ $request_headers 必选参数,表示在实际请求中会用到的除了简单头部之外的headers
+ $options 可选参数,无需设置
+
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 07:03:39 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594E24B031C87E5461606A1
+ )
+
+ [body] =>
+ )
+
+ `
+
+
+* 删除CORS规则
+ * 示例代码
+
+ `
+
+ $bucket_name = "bucket name";
+ $options = null;
+ $response = $client->delete_bucket_cors($bucket_name,$options);
+
+ `
+ * 参数说明
+
+ `
+
+ $bucket_name 必须参数,必须符合bucket命名规范
+ $options 可选参数,无需设置
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array
+ (
+ [status] => 204
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 07:03:39 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594E24B031C87E5461606A2
+ )
+
+ [body] =>
+ )
+
+ `
+
+## 静态网站托管(WebSite)
+* 设置WebSite
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $index_document = 'index.html';
+ $error_document = 'error.html';
+ $options = null;
+ $response = $client->set_bucket_website($bucket_name,$index_document,$error_document,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必须参数,必须符合bucket命名规范
+ $index_document 必选参数,开启website功能,必须设置index_document
+ $error_document 可选参数,自行决定在开启website功能时,是否设置error_document
+ $options 可选参数,无需设置
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 02:39:23 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594A45B58DB3AB75215E239
+ )
+
+ [body] =>
+ )
+
+ `
+
+* 获取WebSite设置
+ * 示例代码
+
+ `
+
+ $bucket_name = "bucket name";
+ $options = null;
+ $response = $client->get_bucket_website($bucket_name,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必须参数,必须符合bucket命名规范
+ $options 可选参数,无需设置
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 02:39:24 GMT
+ [content-type] => application/xml
+ [content-length] => 218
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594A45C031C87E54615DF98
+ )
+
+ [body] => Array(
+ [WebsiteConfiguration] => Array(
+ [IndexDocument] => Array(
+ [Suffix] => index.html
+ )
+
+ [ErrorDocument] => Array(
+ [Key] => error.html
+ )
+ )
+ )
+ )
+
+
+ `
+
+* 删除WebSite
+ * 示例代码
+
+ `
+
+ $bucket_name = "bucket name";
+ $options = null;
+ $response = $client->delete_bucket_website($bucket_name,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必须参数,必须符合bucket命名规范
+ $options 可选参数,无需设置
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 204
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 02:39:24 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594A45C031C87E54615DF99
+ )
+ [body] =>
+ )
+
+ `
+
+## 日志管理(Logging)
+* 设置Logging
+ * 示例代码
+
+ `
+
+ $bucket_name = "bucket name";
+ $target_bucket_name = "logging target bucket";
+ $target_prefix = "logging file prefix";
+ $options = null;
+ $response = $client->set_bucket_logging($bucket_name,$target_bucket_name,$target_prefix,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必须参数,必须符合bucket命名规范;且必须是属于owner的存在的bucket
+ $target_bucket_name 必须参数,日志保存的目标bucket,且必须和要记录日志的bucket在同一集群
+ $target_prefix 可选参数,如果设置,日志文件的名称为 $target_prefix + oss日志规范命名
+ $options 可选参数,无需设置
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 01:59:06 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 55949AEA031C87E54615D996
+ )
+
+ [body] =>
+ )
+
+ `
+
+* 获取logging设置
+ * 示例代码
+
+ `
+
+ $bucket_name = "bucket name";
+ $options = null;
+ $response = $client->get_bucket_logging($bucket_name,$options);
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $options 可选参数,无需设置
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 02:14:09 GMT
+ [content-length] => 235
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 55949E7158DB3AB75215DE78
+ )
+
+ [body] => Array(
+ [BucketLoggingStatus] => Array(
+ [LoggingEnabled] => Array(
+ [TargetBucket] => a-00000000000000000003
+ [TargetPrefix] => common-bucket-logging-
+ )
+ )
+ )
+ )
+
+ `
+
+* 删除Logging
+ * 示例代码
+
+ `
+
+ $bucket_name = "bucket name";
+ $options = null;
+ $response = $client->get_bucket_logging($bucket_name,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $options 可选参数,无需设置
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 204
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 02:29:12 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594A1F858DB3AB75215E0C4
+ )
+
+ [body] =>
+ )
+
+ `
+
+
+## 防盗链(Referer)
+* 设置Referer防盗链
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $is_allow_empty_referer = true;
+ $referer_list = array(
+ 'http://aliyun.com',
+ 'http://sina.com.cn'
+ );
+ $options = null;
+ $response = $client->set_bucket_referer($bucket_name,$is_allow_empty_referer,$referer_list,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $is_allow_empty_referer 必选参数,是否允许空referer,默认为true
+ $referer_list 可选参数,允许的refer白名单列表,注意每条记录均需以http://开头
+ $options 可选参数,无需设置
+
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 03:30:46 GMT
+ [content-length] => 0
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594B06658DB3AB75215E9EC
+ )
+
+ [body] =>
+ )
+
+ `
+
+* 获取Referer设置
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $options = null;
+ $response = $client->get_bucket_referer($bucket_name,$options);
+
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,必须符合bucket命名规范
+ $options 可选参数,无需设置
+
+ `
+
+ * 响应结果
+
+ `
+ 将结果Response转换成array得到,下同
+
+ Array(
+ [status] => 200
+ [header] => Array(
+ [date] => Thu, 02 Jul 2015 03:30:46 GMT
+ [content-type] => application/xml
+ [content-length] => 248
+ [connection] => close
+ [server] => AliyunOSS
+ [x-oss-request-id] => 5594B06658DB3AB75215E9F2
+ )
+
+ [body] => Array(
+ [RefererConfiguration] => Array(
+ [AllowEmptyReferer] => true
+ [RefererList] => Array(
+ [Referer] => Array(
+ [0] => http://aliyun.com
+ [1] => http://sina.com.cn
+ )
+ )
+ )
+ )
+ )
+
+ `
+
+## URL签名操作
+* 获取Get签名URL
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $object_name = 'object name';
+ $timeout = 3600;
+ $options = null;
+ $signed_url = $client->get_sign_url($bucket_name,$object_name,$timeout,$options);
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,参数需要符合bucket命名规范
+ $object_name 必选参数,参数需要符合object命名规范
+ $timeout 必选参数,过期时间
+ $options 可选参数,无需设置
+
+ `
+
+
+ * 响应结果
+
+ `
+
+ http://common-bucket.oss-cn-shanghai.aliyuncs.com/my_get_file.log?OSSAccessKeyId=ACSb***&Expires=1435820652&
+ Signature=AW5z87zmaLulEmvMzf6ZOUrVboE%3D
+
+ `
+
+* 获取Get或Put签名URL
+ * 示例代码
+
+ `
+
+ $bucket_name = 'bucket name';
+ $object_name = 'object name';
+ $timeout = 3600;
+ $method = ALIOSS::OSS_HTTP_GET;
+ $options = null;
+ $signed_url = $client->get_sign_url($bucket_name,$object_name,$timeout,$method,$options);
+ `
+
+ * 参数说明
+
+ `
+
+ $bucket_name 必选参数,参数需要符合bucket命名规范
+ $object_name 必选参数,参数需要符合object命名规范
+ $timeout 必选参数,过期时间
+ $method 必选参数,方法类型,目前支持GET、PUT
+ $options 可选参数,无需设置
+
+ `
+
+
+ * 响应结果
+
+ `
+
+ http://common-bucket.oss-cn-shanghai.aliyuncs.com/my_get_file.log?OSSAccessKeyId=ACSb***&Expires=1435820652&
+ Signature=AW5z87zmaLulEmvMzf6ZOUrVboE%3D
+
+ `
+
diff --git a/AliOssSdk/lang/zh.inc.php b/AliOssSdk/lang/zh.inc.php
new file mode 100644
index 0000000..368ea2a
--- /dev/null
+++ b/AliOssSdk/lang/zh.inc.php
@@ -0,0 +1,99 @@
+. You can get the code from .
+
+### License and Copyright
+
+This code is Copyright (c) 2008-2010, Ryan Parman. However, I'm licensing this code for others to use under the [Simplified BSD license](http://www.opensource.org/licenses/bsd-license.php).
diff --git a/AliOssSdk/lib/requestcore/requestcore.class.php b/AliOssSdk/lib/requestcore/requestcore.class.php
new file mode 100644
index 0000000..f475859
--- /dev/null
+++ b/AliOssSdk/lib/requestcore/requestcore.class.php
@@ -0,0 +1,1030 @@
+).
+ */
+ public $request_class = 'RequestCore';
+
+ /**
+ * The default class to use for HTTP Responses (defaults to ).
+ */
+ public $response_class = 'ResponseCore';
+
+ /**
+ * Default useragent string to use.
+ */
+ public $useragent = 'RequestCore/1.4.3';
+
+ /**
+ * File to read from while streaming up.
+ */
+ public $read_file = null;
+
+ /**
+ * The resource to read from while streaming up.
+ */
+ public $read_stream = null;
+
+ /**
+ * The size of the stream to read from.
+ */
+ public $read_stream_size = null;
+
+ /**
+ * The length already read from the stream.
+ */
+ public $read_stream_read = 0;
+
+ /**
+ * File to write to while streaming down.
+ */
+ public $write_file = null;
+
+ /**
+ * The resource to write to while streaming down.
+ */
+ public $write_stream = null;
+
+ /**
+ * Stores the intended starting seek position.
+ */
+ public $seek_position = null;
+
+ /**
+ * The location of the cacert.pem file to use.
+ */
+ public $cacert_location = false;
+
+ /**
+ * The state of SSL certificate verification.
+ */
+ public $ssl_verification = true;
+
+ /**
+ * The user-defined callback function to call when a stream is read from.
+ */
+ public $registered_streaming_read_callback = null;
+
+ /**
+ * The user-defined callback function to call when a stream is written to.
+ */
+ public $registered_streaming_write_callback = null;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTANTS
+
+ /**
+ * GET HTTP Method
+ */
+ const HTTP_GET = 'GET';
+
+ /**
+ * POST HTTP Method
+ */
+ const HTTP_POST = 'POST';
+
+ /**
+ * PUT HTTP Method
+ */
+ const HTTP_PUT = 'PUT';
+
+ /**
+ * DELETE HTTP Method
+ */
+ const HTTP_DELETE = 'DELETE';
+
+ /**
+ * HEAD HTTP Method
+ */
+ const HTTP_HEAD = 'HEAD';
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR/DESTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $url (Optional) The URL to request or service endpoint to query.
+ * @param string $proxy (Optional) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
+ * @param array $helpers (Optional) An associative array of classnames to use for request, and response functionality. Gets passed in automatically by the calling class.
+ * @return $this A reference to the current instance.
+ */
+ public function __construct($url = null, $proxy = null, $helpers = null)
+ {
+ // Set some default values.
+ $this->request_url = $url;
+ $this->method = self::HTTP_GET;
+ $this->request_headers = array();
+ $this->request_body = '';
+
+ // Set a new Request class if one was set.
+ if (isset($helpers['request']) && !empty($helpers['request']))
+ {
+ $this->request_class = $helpers['request'];
+ }
+
+ // Set a new Request class if one was set.
+ if (isset($helpers['response']) && !empty($helpers['response']))
+ {
+ $this->response_class = $helpers['response'];
+ }
+
+ if ($proxy)
+ {
+ $this->set_proxy($proxy);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Destructs the instance. Closes opened file handles.
+ *
+ * @return $this A reference to the current instance.
+ */
+ public function __destruct()
+ {
+ if (isset($this->read_file) && isset($this->read_stream))
+ {
+ fclose($this->read_stream);
+ }
+
+ if (isset($this->write_file) && isset($this->write_stream))
+ {
+ fclose($this->write_stream);
+ }
+
+ return $this;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // REQUEST METHODS
+
+ /**
+ * Sets the credentials to use for authentication.
+ *
+ * @param string $user (Required) The username to authenticate with.
+ * @param string $pass (Required) The password to authenticate with.
+ * @return $this A reference to the current instance.
+ */
+ public function set_credentials($user, $pass)
+ {
+ $this->username = $user;
+ $this->password = $pass;
+ return $this;
+ }
+
+ /**
+ * Adds a custom HTTP header to the cURL request.
+ *
+ * @param string $key (Required) The custom HTTP header to set.
+ * @param mixed $value (Required) The value to assign to the custom HTTP header.
+ * @return $this A reference to the current instance.
+ */
+ public function add_header($key, $value)
+ {
+ $this->request_headers[$key] = $value;
+ return $this;
+ }
+
+ /**
+ * Removes an HTTP header from the cURL request.
+ *
+ * @param string $key (Required) The custom HTTP header to set.
+ * @return $this A reference to the current instance.
+ */
+ public function remove_header($key)
+ {
+ if (isset($this->request_headers[$key]))
+ {
+ unset($this->request_headers[$key]);
+ }
+ return $this;
+ }
+
+ /**
+ * Set the method type for the request.
+ *
+ * @param string $method (Required) One of the following constants: , , , , .
+ * @return $this A reference to the current instance.
+ */
+ public function set_method($method)
+ {
+ $this->method = strtoupper($method);
+ return $this;
+ }
+
+ /**
+ * Sets a custom useragent string for the class.
+ *
+ * @param string $ua (Required) The useragent string to use.
+ * @return $this A reference to the current instance.
+ */
+ public function set_useragent($ua)
+ {
+ $this->useragent = $ua;
+ return $this;
+ }
+
+ /**
+ * Set the body to send in the request.
+ *
+ * @param string $body (Required) The textual content to send along in the body of the request.
+ * @return $this A reference to the current instance.
+ */
+ public function set_body($body)
+ {
+ $this->request_body = $body;
+ return $this;
+ }
+
+ /**
+ * Set the URL to make the request to.
+ *
+ * @param string $url (Required) The URL to make the request to.
+ * @return $this A reference to the current instance.
+ */
+ public function set_request_url($url)
+ {
+ $this->request_url = $url;
+ return $this;
+ }
+
+ /**
+ * Set additional CURLOPT settings. These will merge with the default settings, and override if
+ * there is a duplicate.
+ *
+ * @param array $curlopts (Optional) A set of key-value pairs that set `CURLOPT` options. These will merge with the existing CURLOPTs, and ones passed here will override the defaults. Keys should be the `CURLOPT_*` constants, not strings.
+ * @return $this A reference to the current instance.
+ */
+ public function set_curlopts($curlopts)
+ {
+ $this->curlopts = $curlopts;
+ return $this;
+ }
+
+ /**
+ * Sets the length in bytes to read from the stream while streaming up.
+ *
+ * @param integer $size (Required) The length in bytes to read from the stream.
+ * @return $this A reference to the current instance.
+ */
+ public function set_read_stream_size($size)
+ {
+ $this->read_stream_size = $size;
+
+ return $this;
+ }
+
+ /**
+ * Sets the resource to read from while streaming up. Reads the stream from its current position until
+ * EOF or `$size` bytes have been read. If `$size` is not given it will be determined by and
+ * .
+ *
+ * @param resource $resource (Required) The readable resource to read from.
+ * @param integer $size (Optional) The size of the stream to read.
+ * @return $this A reference to the current instance.
+ */
+ public function set_read_stream($resource, $size = null)
+ {
+ if (!isset($size) || $size < 0)
+ {
+ $stats = fstat($resource);
+
+ if ($stats && $stats['size'] >= 0)
+ {
+ $position = ftell($resource);
+
+ if ($position !== false && $position >= 0)
+ {
+ $size = $stats['size'] - $position;
+ }
+ }
+ }
+
+ $this->read_stream = $resource;
+
+ return $this->set_read_stream_size($size);
+ }
+
+ /**
+ * Sets the file to read from while streaming up.
+ *
+ * @param string $location (Required) The readable location to read from.
+ * @return $this A reference to the current instance.
+ */
+ public function set_read_file($location)
+ {
+ $this->read_file = $location;
+ $read_file_handle = fopen($location, 'r');
+
+ return $this->set_read_stream($read_file_handle);
+ }
+
+ /**
+ * Sets the resource to write to while streaming down.
+ *
+ * @param resource $resource (Required) The writeable resource to write to.
+ * @return $this A reference to the current instance.
+ */
+ public function set_write_stream($resource)
+ {
+ $this->write_stream = $resource;
+
+ return $this;
+ }
+
+ /**
+ * Sets the file to write to while streaming down.
+ *
+ * @param string $location (Required) The writeable location to write to.
+ * @return $this A reference to the current instance.
+ */
+ public function set_write_file($location)
+ {
+ $this->write_file = $location;
+ $write_file_handle = fopen($location, 'w');
+
+ return $this->set_write_stream($write_file_handle);
+ }
+
+ /**
+ * Set the proxy to use for making requests.
+ *
+ * @param string $proxy (Required) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
+ * @return $this A reference to the current instance.
+ */
+ public function set_proxy($proxy)
+ {
+ $proxy = parse_url($proxy);
+ $proxy['user'] = isset($proxy['user']) ? $proxy['user'] : null;
+ $proxy['pass'] = isset($proxy['pass']) ? $proxy['pass'] : null;
+ $proxy['port'] = isset($proxy['port']) ? $proxy['port'] : null;
+ $this->proxy = $proxy;
+ return $this;
+ }
+
+ /**
+ * Set the intended starting seek position.
+ *
+ * @param integer $position (Required) The byte-position of the stream to begin reading from.
+ * @return $this A reference to the current instance.
+ */
+ public function set_seek_position($position)
+ {
+ $this->seek_position = isset($position) ? (integer) $position : null;
+
+ return $this;
+ }
+
+ /**
+ * Register a callback function to execute whenever a data stream is read from using
+ * .
+ *
+ * The user-defined callback function should accept three arguments:
+ *
+ *
+ * $curl_handle - resource - Required - The cURL handle resource that represents the in-progress transfer.
+ * $file_handle - resource - Required - The file handle resource that represents the file on the local file system.
+ * $length - integer - Required - The length in kilobytes of the data chunk that was transferred.
+ *
+ *
+ * @param string|array|function $callback (Required) The callback function is called by , so you can pass the following values:
+ * - The name of a global function to execute, passed as a string.
+ * - A method to execute, passed as
array('ClassName', 'MethodName') .
+ * - An anonymous function (PHP 5.3+).
+ * @return $this A reference to the current instance.
+ */
+ public function register_streaming_read_callback($callback)
+ {
+ $this->registered_streaming_read_callback = $callback;
+
+ return $this;
+ }
+
+ /**
+ * Register a callback function to execute whenever a data stream is written to using
+ * .
+ *
+ * The user-defined callback function should accept two arguments:
+ *
+ *
+ * $curl_handle - resource - Required - The cURL handle resource that represents the in-progress transfer.
+ * $length - integer - Required - The length in kilobytes of the data chunk that was transferred.
+ *
+ *
+ * @param string|array|function $callback (Required) The callback function is called by , so you can pass the following values:
+ * - The name of a global function to execute, passed as a string.
+ * - A method to execute, passed as
array('ClassName', 'MethodName') .
+ * - An anonymous function (PHP 5.3+).
+ * @return $this A reference to the current instance.
+ */
+ public function register_streaming_write_callback($callback)
+ {
+ $this->registered_streaming_write_callback = $callback;
+
+ return $this;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // PREPARE, SEND, AND PROCESS REQUEST
+
+ /**
+ * A callback function that is invoked by cURL for streaming up.
+ *
+ * @param resource $curl_handle (Required) The cURL handle for the request.
+ * @param resource $file_handle (Required) The open file handle resource.
+ * @param integer $length (Required) The maximum number of bytes to read.
+ * @return binary Binary data from a stream.
+ */
+ public function streaming_read_callback($curl_handle, $file_handle, $length)
+ {
+ // Once we've sent as much as we're supposed to send...
+ if ($this->read_stream_read >= $this->read_stream_size)
+ {
+ // Send EOF
+ return '';
+ }
+
+ // If we're at the beginning of an upload and need to seek...
+ if ($this->read_stream_read == 0 && isset($this->seek_position) && $this->seek_position !== ftell($this->read_stream))
+ {
+ if (fseek($this->read_stream, $this->seek_position) !== 0)
+ {
+ throw new RequestCore_Exception('The stream does not support seeking and is either not at the requested position or the position is unknown.');
+ }
+ }
+
+ $read = fread($this->read_stream, min($this->read_stream_size - $this->read_stream_read, $length)); // Remaining upload data or cURL's requested chunk size
+ $this->read_stream_read += strlen($read);
+
+ $out = $read === false ? '' : $read;
+
+ // Execute callback function
+ if ($this->registered_streaming_read_callback)
+ {
+ call_user_func($this->registered_streaming_read_callback, $curl_handle, $file_handle, $out);
+ }
+
+ return $out;
+ }
+
+ /**
+ * A callback function that is invoked by cURL for streaming down.
+ *
+ * @param resource $curl_handle (Required) The cURL handle for the request.
+ * @param binary $data (Required) The data to write.
+ * @return integer The number of bytes written.
+ */
+ public function streaming_write_callback($curl_handle, $data)
+ {
+ $length = strlen($data);
+ $written_total = 0;
+ $written_last = 0;
+
+ while ($written_total < $length)
+ {
+ $written_last = fwrite($this->write_stream, substr($data, $written_total));
+
+ if ($written_last === false)
+ {
+ return $written_total;
+ }
+
+ $written_total += $written_last;
+ }
+
+ // Execute callback function
+ if ($this->registered_streaming_write_callback)
+ {
+ call_user_func($this->registered_streaming_write_callback, $curl_handle, $written_total);
+ }
+
+ return $written_total;
+ }
+
+ /**
+ * Prepares and adds the details of the cURL request. This can be passed along to a
+ * function.
+ *
+ * @return resource The handle for the cURL object.
+ */
+ public function prep_request()
+ {
+ $curl_handle = curl_init();
+
+ // Set default options.
+ curl_setopt($curl_handle, CURLOPT_URL, $this->request_url);
+ curl_setopt($curl_handle, CURLOPT_FILETIME, true);
+ curl_setopt($curl_handle, CURLOPT_FRESH_CONNECT, false);
+ curl_setopt($curl_handle, CURLOPT_CLOSEPOLICY, CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
+ curl_setopt($curl_handle, CURLOPT_MAXREDIRS, 5);
+ curl_setopt($curl_handle, CURLOPT_HEADER, true);
+ curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl_handle, CURLOPT_TIMEOUT, 5184000);
+ curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 120);
+ curl_setopt($curl_handle, CURLOPT_NOSIGNAL, true);
+ curl_setopt($curl_handle, CURLOPT_REFERER, $this->request_url);
+ curl_setopt($curl_handle, CURLOPT_USERAGENT, $this->useragent);
+ curl_setopt($curl_handle, CURLOPT_READFUNCTION, array($this, 'streaming_read_callback'));
+
+ // Verification of the SSL cert
+ if ($this->ssl_verification)
+ {
+ curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
+ }
+ else
+ {
+ curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, false);
+ }
+
+ // chmod the file as 0755
+ if ($this->cacert_location === true)
+ {
+ curl_setopt($curl_handle, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
+ }
+ elseif (is_string($this->cacert_location))
+ {
+ curl_setopt($curl_handle, CURLOPT_CAINFO, $this->cacert_location);
+ }
+
+ // Debug mode
+ if ($this->debug_mode)
+ {
+ curl_setopt($curl_handle, CURLOPT_VERBOSE, true);
+ }
+
+ // Handle open_basedir & safe mode
+ if (!ini_get('safe_mode') && !ini_get('open_basedir'))
+ {
+ curl_setopt($curl_handle, CURLOPT_FOLLOWLOCATION, true);
+ }
+
+ // Enable a proxy connection if requested.
+ if ($this->proxy)
+ {
+ curl_setopt($curl_handle, CURLOPT_HTTPPROXYTUNNEL, true);
+
+ $host = $this->proxy['host'];
+ $host .= ($this->proxy['port']) ? ':' . $this->proxy['port'] : '';
+ curl_setopt($curl_handle, CURLOPT_PROXY, $host);
+
+ if (isset($this->proxy['user']) && isset($this->proxy['pass']))
+ {
+ curl_setopt($curl_handle, CURLOPT_PROXYUSERPWD, $this->proxy['user'] . ':' . $this->proxy['pass']);
+ }
+ }
+
+ // Set credentials for HTTP Basic/Digest Authentication.
+ if ($this->username && $this->password)
+ {
+ curl_setopt($curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+ curl_setopt($curl_handle, CURLOPT_USERPWD, $this->username . ':' . $this->password);
+ }
+
+ // Handle the encoding if we can.
+ if (extension_loaded('zlib'))
+ {
+ curl_setopt($curl_handle, CURLOPT_ENCODING, '');
+ }
+
+ // Process custom headers
+ if (isset($this->request_headers) && count($this->request_headers))
+ {
+ $temp_headers = array();
+
+ foreach ($this->request_headers as $k => $v)
+ {
+ $temp_headers[] = $k . ': ' . $v;
+ }
+
+ curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $temp_headers);
+ }
+
+ switch ($this->method)
+ {
+ case self::HTTP_PUT:
+ //unset($this->read_stream);
+ curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, 'PUT');
+ if (isset($this->read_stream))
+ {
+ if (!isset($this->read_stream_size) || $this->read_stream_size < 0)
+ {
+ throw new RequestCore_Exception('The stream size for the streaming upload cannot be determined.');
+ }
+
+ curl_setopt($curl_handle, CURLOPT_INFILESIZE, $this->read_stream_size);
+ curl_setopt($curl_handle, CURLOPT_UPLOAD, true);
+ }
+ else
+ {
+ curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
+ }
+ break;
+
+ case self::HTTP_POST:
+ curl_setopt($curl_handle, CURLOPT_POST, true);
+ curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
+ break;
+
+ case self::HTTP_HEAD:
+ curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, self::HTTP_HEAD);
+ curl_setopt($curl_handle, CURLOPT_NOBODY, 1);
+ break;
+
+ default: // Assumed GET
+ curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, $this->method);
+ if (isset($this->write_stream))
+ {
+ curl_setopt($curl_handle, CURLOPT_WRITEFUNCTION, array($this, 'streaming_write_callback'));
+ curl_setopt($curl_handle, CURLOPT_HEADER, false);
+ }
+ else
+ {
+ curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
+ }
+ break;
+ }
+
+ // Merge in the CURLOPTs
+ if (isset($this->curlopts) && sizeof($this->curlopts) > 0)
+ {
+ foreach ($this->curlopts as $k => $v)
+ {
+ curl_setopt($curl_handle, $k, $v);
+ }
+ }
+
+ return $curl_handle;
+ }
+
+ /**
+ * Take the post-processed cURL data and break it down into useful header/body/info chunks. Uses the
+ * data stored in the `curl_handle` and `response` properties unless replacement data is passed in via
+ * parameters.
+ *
+ * @param resource $curl_handle (Optional) The reference to the already executed cURL request.
+ * @param string $response (Optional) The actual response content itself that needs to be parsed.
+ * @return ResponseCore A object containing a parsed HTTP response.
+ */
+ public function process_response($curl_handle = null, $response = null)
+ {
+ // Accept a custom one if it's passed.
+ if ($curl_handle && $response)
+ {
+ $this->curl_handle = $curl_handle;
+ $this->response = $response;
+ }
+
+ // As long as this came back as a valid resource...
+ if (is_resource($this->curl_handle))
+ {
+ // Determine what's what.
+ $header_size = curl_getinfo($this->curl_handle, CURLINFO_HEADER_SIZE);
+ $this->response_headers = substr($this->response, 0, $header_size);
+ $this->response_body = substr($this->response, $header_size);
+ $this->response_code = curl_getinfo($this->curl_handle, CURLINFO_HTTP_CODE);
+ $this->response_info = curl_getinfo($this->curl_handle);
+
+ // Parse out the headers
+ $this->response_headers = explode("\r\n\r\n", trim($this->response_headers));
+ $this->response_headers = array_pop($this->response_headers);
+ $this->response_headers = explode("\r\n", $this->response_headers);
+ array_shift($this->response_headers);
+
+ // Loop through and split up the headers.
+ $header_assoc = array();
+ foreach ($this->response_headers as $header)
+ {
+ $kv = explode(': ', $header);
+ $header_assoc[strtolower($kv[0])] = isset($kv[1])?$kv[1]:'';
+ }
+
+ // Reset the headers to the appropriate property.
+ $this->response_headers = $header_assoc;
+ $this->response_headers['_info'] = $this->response_info;
+ $this->response_headers['_info']['method'] = $this->method;
+
+ if ($curl_handle && $response)
+ {
+ return new $this->response_class($this->response_headers, $this->response_body, $this->response_code, $this->curl_handle);
+ }
+ }
+
+ // Return false
+ return false;
+ }
+
+ /**
+ * Sends the request, calling necessary utility functions to update built-in properties.
+ *
+ * @param boolean $parse (Optional) Whether to parse the response with ResponseCore or not.
+ * @return string The resulting unparsed data from the request.
+ */
+ public function send_request($parse = false)
+ {
+ set_time_limit(0);
+
+ $curl_handle = $this->prep_request();
+ $this->response = curl_exec($curl_handle);
+
+ if ($this->response === false)
+ {
+ throw new RequestCore_Exception('cURL resource: ' . (string) $curl_handle . '; cURL error: ' . curl_error($curl_handle) . ' (' . curl_errno($curl_handle) . ')');
+ }
+
+ $parsed_response = $this->process_response($curl_handle, $this->response);
+
+ curl_close($curl_handle);
+
+ if ($parse)
+ {
+ return $parsed_response;
+ }
+
+ return $this->response;
+ }
+
+ /**
+ * Sends the request using , enabling parallel requests. Uses the "rolling" method.
+ *
+ * @param array $handles (Required) An indexed array of cURL handles to process simultaneously.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys:
+ * callback - string|array - Optional - The string name of a function to pass the response data to. If this is a method, pass an array where the [0] index is the class and the [1] index is the method name.
+ * limit - integer - Optional - The number of simultaneous requests to make. This can be useful for scaling around slow server responses. Defaults to trusting cURLs judgement as to how many to use.
+ * @return array Post-processed cURL responses.
+ */
+ public function send_multi_request($handles, $opt = null)
+ {
+ set_time_limit(0);
+
+ // Skip everything if there are no handles to process.
+ if (count($handles) === 0) return array();
+
+ if (!$opt) $opt = array();
+
+ // Initialize any missing options
+ $limit = isset($opt['limit']) ? $opt['limit'] : -1;
+
+ // Initialize
+ $handle_list = $handles;
+ $http = new $this->request_class();
+ $multi_handle = curl_multi_init();
+ $handles_post = array();
+ $added = count($handles);
+ $last_handle = null;
+ $count = 0;
+ $i = 0;
+
+ // Loop through the cURL handles and add as many as it set by the limit parameter.
+ while ($i < $added)
+ {
+ if ($limit > 0 && $i >= $limit) break;
+ curl_multi_add_handle($multi_handle, array_shift($handles));
+ $i++;
+ }
+
+ do
+ {
+ $active = false;
+
+ // Start executing and wait for a response.
+ while (($status = curl_multi_exec($multi_handle, $active)) === CURLM_CALL_MULTI_PERFORM)
+ {
+ // Start looking for possible responses immediately when we have to add more handles
+ if (count($handles) > 0) break;
+ }
+
+ // Figure out which requests finished.
+ $to_process = array();
+
+ while ($done = curl_multi_info_read($multi_handle))
+ {
+ // Since curl_errno() isn't reliable for handles that were in multirequests, we check the 'result' of the info read, which contains the curl error number, (listed here http://curl.haxx.se/libcurl/c/libcurl-errors.html )
+ if ($done['result'] > 0)
+ {
+ throw new RequestCore_Exception('cURL resource: ' . (string) $done['handle'] . '; cURL error: ' . curl_error($done['handle']) . ' (' . $done['result'] . ')');
+ }
+
+ // Because curl_multi_info_read() might return more than one message about a request, we check to see if this request is already in our array of completed requests
+ elseif (!isset($to_process[(int) $done['handle']]))
+ {
+ $to_process[(int) $done['handle']] = $done;
+ }
+ }
+
+ // Actually deal with the request
+ foreach ($to_process as $pkey => $done)
+ {
+ $response = $http->process_response($done['handle'], curl_multi_getcontent($done['handle']));
+ $key = array_search($done['handle'], $handle_list, true);
+ $handles_post[$key] = $response;
+
+ if (count($handles) > 0)
+ {
+ curl_multi_add_handle($multi_handle, array_shift($handles));
+ }
+
+ curl_multi_remove_handle($multi_handle, $done['handle']);
+ curl_close($done['handle']);
+ }
+ }
+ while ($active || count($handles_post) < $added);
+
+ curl_multi_close($multi_handle);
+
+ ksort($handles_post, SORT_NUMERIC);
+ return $handles_post;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // RESPONSE METHODS
+
+ /**
+ * Get the HTTP response headers from the request.
+ *
+ * @param string $header (Optional) A specific header value to return. Defaults to all headers.
+ * @return string|array All or selected header values.
+ */
+ public function get_response_header($header = null)
+ {
+ if ($header)
+ {
+ return $this->response_headers[strtolower($header)];
+ }
+ return $this->response_headers;
+ }
+
+ /**
+ * Get the HTTP response body from the request.
+ *
+ * @return string The response body.
+ */
+ public function get_response_body()
+ {
+ return $this->response_body;
+ }
+
+ /**
+ * Get the HTTP response code from the request.
+ *
+ * @return string The HTTP response code.
+ */
+ public function get_response_code()
+ {
+ return $this->response_code;
+ }
+}
+
+
+/**
+ * Container for all response-related methods.
+ */
+class ResponseCore
+{
+ /**
+ * Stores the HTTP header information.
+ */
+ public $header;
+
+ /**
+ * Stores the SimpleXML response.
+ */
+ public $body;
+
+ /**
+ * Stores the HTTP response code.
+ */
+ public $status;
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param array $header (Required) Associative array of HTTP headers (typically returned by ).
+ * @param string $body (Required) XML-formatted response from AWS.
+ * @param integer $status (Optional) HTTP response status code from the request.
+ * @return object Contains an `header` property (HTTP headers as an associative array), a or `body` property, and an `status` code.
+ */
+ public function __construct($header, $body, $status = null)
+ {
+ $this->header = $header;
+ $this->body = $body;
+ $this->status = $status;
+
+ return $this;
+ }
+
+ /**
+ * Did we receive the status code we expected?
+ *
+ * @param integer|array $codes (Optional) The status code(s) to expect. Pass an for a single acceptable value, or an of integers for multiple acceptable values.
+ * @return boolean Whether we received the expected status code or not.
+ */
+ public function isOK($codes = array(200, 201, 204, 206))
+ {
+ if (is_array($codes))
+ {
+ return in_array($this->status, $codes);
+ }
+
+ return $this->status === $codes;
+ }
+}
+
+/**
+ * Default RequestCore Exception.
+ */
+class RequestCore_Exception extends Exception {}
diff --git a/AliOssSdk/sdk.class.php b/AliOssSdk/sdk.class.php
new file mode 100644
index 0000000..1663638
--- /dev/null
+++ b/AliOssSdk/sdk.class.php
@@ -0,0 +1,2104 @@
+access_id = $access_id;
+ $this->access_key = $access_key;
+ }elseif (defined('OSS_ACCESS_ID') && defined('OSS_ACCESS_KEY')){
+ $this->access_id = OSS_ACCESS_ID;
+ $this->access_key = OSS_ACCESS_KEY;
+ }else{
+ throw new OSS_Exception(NOT_SET_OSS_ACCESS_ID_AND_ACCESS_KEY);
+ }
+ if(empty($this->access_id) || empty($this->access_key)){
+ throw new OSS_Exception(OSS_ACCESS_ID_OR_ACCESS_KEY_EMPTY);
+ }
+ if ($hostname) {
+ $this->hostname = $hostname;
+ }
+ else if (!$hostname and defined('OSS_ENDPOINT')) {
+ $this->hostname = OSS_ENDPOINT;
+ }else{
+ $this->hostname = self::DEFAULT_OSS_ENDPOINT;
+ }
+
+ //支持sts的security token
+ $this->security_token = $security_token;
+ }
+
+
+ /*%******************************************************************************************************%*/
+ //Service Operation
+ /**
+ * 获取bucket列表
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function list_bucket($options = NULL) {
+ $this->precheck_options($options);
+ $options[self::OSS_BUCKET] = '';
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_OBJECT] = '/';
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /*%******************************************************************************************************%*/
+ //Bucket Operation
+ /**
+ * 创建bucket
+ * @param string $bucket (Required)
+ * @param string $acl (Optional)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function create_bucket($bucket, $acl = self::OSS_ACL_TYPE_PRIVATE, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_HEADERS] = array(self::OSS_ACL => $acl);
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /**
+ * 删除bucket
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function delete_bucket($bucket, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+ $options[self::OSS_OBJECT] = '/';
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /**
+ * 获取bucket的acl
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function get_bucket_acl($bucket, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'acl';
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /**
+ * 设置bucket的acl
+ * @param string $bucket (Required)
+ * @param string $acl (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function set_bucket_acl($bucket, $acl, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_HEADERS] = array(self::OSS_ACL => $acl);
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /**
+ * 获取bucket logging
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author lijie.ma@alibaba-inc.com
+ * @since 2014-05-04
+ * @return ResponseCore
+ */
+ public function get_bucket_logging($bucket, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'logging';
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /**
+ * 设置bucket Logging
+ * @param string $bucket (Required)
+ * @param string $target_bucket (Required)
+ * @param string $target_prefix (Optional)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author lijie.ma@alibaba-inc.com
+ * @since 2014-05-04
+ * @return ResponseCore
+ */
+ public function set_bucket_logging($bucket, $target_bucket, $target_prefix, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $this->precheck_bucket($target_bucket, OSS_TARGET_BUCKET_IS_NOT_ALLOWED_EMPTY);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'logging';
+ $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+ $xml = new SimpleXMLElement('');
+ $logging_enabled_part=$xml->addChild('LoggingEnabled');
+ $logging_enabled_part->addChild('TargetBucket', $target_bucket);
+ $logging_enabled_part->addChild('TargetPrefix', $target_prefix);
+ $options[self::OSS_CONTENT] = $xml->asXML();
+ return $this->auth($options);
+ }
+
+ /**
+ * 删除bucket logging
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author lijie.ma@alibaba-inc.com
+ * @since 2014-05-04
+ * @return ResponseCore
+ */
+ public function delete_bucket_logging($bucket, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'logging';
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /**
+ * 设置bucket website
+ * @param string $bucket (Required)
+ * @param string $index_document (Required)
+ * @param string $error_document (Optional)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author lijie.ma@alibaba-inc.com
+ * @since 2014-05-04
+ * @return ResponseCore
+ */
+ public function set_bucket_website($bucket, $index_document, $error_document, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ OSSUtil::is_empty($index_document, OSS_INDEX_DOCUMENT_IS_NOT_ALLOWED_EMPTY);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'website';
+ $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+
+ $xml = new SimpleXMLElement('');
+ $index_document_part=$xml->addChild('IndexDocument');
+ $error_document_part=$xml->addChild('ErrorDocument');
+ $index_document_part->addChild('Suffix', $index_document);
+ $error_document_part->addChild('Key', $error_document);
+ $options[self::OSS_CONTENT] = $xml->asXML();
+ return $this->auth($options);
+ }
+
+ /**
+ * 获取bucket website
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author lijie.ma@alibaba-inc.com
+ * @since 2014-05-04
+ * @return ResponseCore
+ */
+ public function get_bucket_website($bucket, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'website';
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /**
+ * 删除bucket website
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author lijie.ma@alibaba-inc.com
+ * @since 2014-05-04
+ * @return ResponseCore
+ */
+ public function delete_bucket_website($bucket, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'website';
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /**
+ * 设置bucket cors
+ * @param string $bucket (Required)
+ * @param array $cors_rules (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author lijie.ma@alibaba-inc.com
+ * @since 2014-05-04
+ * @return ResponseCore
+ */
+ public function set_bucket_cors($bucket, $cors_rules, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'cors';
+ $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+ $xml = new SimpleXMLElement('');
+ foreach ($cors_rules as $cors_rule){
+ $cors_rule_part = $xml->addChild('CORSRule');
+ foreach ($cors_rule[self::OSS_CORS_ALLOWED_ORIGIN] as $value){
+ $cors_rule_part->addChild(self::OSS_CORS_ALLOWED_ORIGIN, $value);
+ }
+ foreach ($cors_rule[self::OSS_CORS_ALLOWED_HEADER] as $value){
+ $cors_rule_part->addChild(self::OSS_CORS_ALLOWED_HEADER, $value);
+ }
+ foreach ($cors_rule[self::OSS_CORS_ALLOWED_METHOD] as $value){
+ $cors_rule_part->addChild(self::OSS_CORS_ALLOWED_METHOD, $value);
+ }
+ foreach ($cors_rule[self::OSS_CORS_EXPOSE_HEADER] as $value){
+ $cors_rule_part->addChild(self::OSS_CORS_EXPOSE_HEADER, $value);
+ }
+ $cors_rule_part->addChild(self::OSS_CORS_MAX_AGE_SECONDS, $cors_rule[self::OSS_CORS_MAX_AGE_SECONDS]);
+ }
+ $options[self::OSS_CONTENT] = $xml->asXML();
+ return $this->auth($options);
+ }
+ /**
+ * 获取bucket cors
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author lijie.ma@alibaba-inc.com
+ * @since 2014-05-04
+ * @return ResponseCore
+ */
+ public function get_bucket_cors($bucket, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'cors';
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /**
+ * 删除bucket cors
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author lijie.ma@alibaba-inc.com
+ * @since 2014-05-04
+ * @return ResponseCore
+ */
+ public function delete_bucket_cors($bucket, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'cors';
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /**
+ * 检验跨域资源请求
+ * @param string $bucket (Required)
+ * @param string $object (Required)
+ * @param string $origin (Required)
+ * @param string $request_method (Required)
+ * @param string $request_headers (Required)
+ * @param array $options (Optional)
+ * @return ResponseCore
+ * @throws OSS_Exception
+ */
+ public function options_object($bucket, $object, $origin, $request_method, $request_headers, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_OPTIONS;
+ $options[self::OSS_OBJECT] = $object;
+ $options[self::OSS_HEADERS] = array(
+ self::OSS_OPTIONS_ORIGIN => $origin,
+ self::OSS_OPTIONS_REQUEST_HEADERS => $request_headers,
+ self::OSS_OPTIONS_REQUEST_METHOD => $request_method
+ );
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /**
+ * 设置bucket lifecycle
+ * @param string $bucket (Required)
+ * @param string $lifecycle_xml (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @since 2015-03-11
+ * @return ResponseCore
+ */
+ public function set_bucket_lifecycle($bucket, $lifecycle_xml, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'lifecycle';
+ $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+ $options[self::OSS_CONTENT] = $lifecycle_xml;
+ return $this->auth($options);
+ }
+
+ /**
+ * 获取bucket lifecycle
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @since 2015-03-11
+ * @return ResponseCore
+ */
+ public function get_bucket_lifecycle($bucket, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'lifecycle';
+ return $this->auth($options);
+ }
+
+ /**
+ * 删除bucket lifecycle
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @since 2015-03-11
+ * @return ResponseCore
+ */
+ public function delete_bucket_lifecycle($bucket, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'lifecycle';
+ return $this->auth($options);
+ }
+
+ /**
+ * 设置bucket referer
+ * @param string $bucket (Required)
+ * @param bool $is_allow_empty_referer (Required)
+ * @param array $referer_list (Optional)
+ * @param array $options (Optional)
+ * @return ResponseCore
+ * @throws OSS_Exception
+ */
+ public function set_bucket_referer($bucket, $is_allow_empty_referer = true, $referer_list = NULL, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'referer';
+ $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+
+ $xml = new SimpleXMLElement('');
+ $list = $xml->addChild('RefererList');
+ if ($referer_list){
+ foreach ($referer_list as $value){
+ $list->addChild('Referer', $value);
+ }
+ }
+ else{
+ $list->addChild('Referer', '');
+ }
+ $value = "true";
+ if (!$is_allow_empty_referer){
+ $value = "false";
+ }
+ $xml->addChild('AllowEmptyReferer', $value);
+ $options[self::OSS_CONTENT] = $xml->asXML();
+ return $this->auth($options);
+ }
+
+ /**
+ * 获取bucket referer
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @since 2015-03-11
+ * @return ResponseCore
+ */
+ public function get_bucket_referer($bucket, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'referer';
+ return $this->auth($options);
+ }
+
+ /*%******************************************************************************************************%*/
+ //Object Operation
+
+ /**
+ * 获取bucket下的object列表
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * 其中options中的参数如下
+ * $options = array(
+ * 'max-keys' => max-keys用于限定此次返回object的最大数,如果不设定,默认为100,max-keys取值不能大于100。
+ * 'prefix' => 限定返回的object key必须以prefix作为前缀。注意使用prefix查询时,返回的key中仍会包含prefix。
+ * 'delimiter' => 是一个用于对Object名字进行分组的字符。所有名字包含指定的前缀且第一次出现delimiter字符之间的object作为一组元素
+ * 'marker' => 用户设定结果从marker之后按字母排序的第一个开始返回。
+ *)
+ * 其中 prefix,marker用来实现分页显示效果,参数的长度必须小于256字节。
+ * @throws OSS_Exception
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function list_object($bucket, $options = NULL){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_HEADERS] = array(
+ self::OSS_DELIMITER => isset($options[self::OSS_DELIMITER])?$options[self::OSS_DELIMITER]:'/',
+ self::OSS_PREFIX => isset($options[self::OSS_PREFIX])?$options[self::OSS_PREFIX]:'',
+ self::OSS_MAX_KEYS => isset($options[self::OSS_MAX_KEYS])?$options[self::OSS_MAX_KEYS]:self::OSS_MAX_KEYS_VALUE,
+ self::OSS_MARKER => isset($options[self::OSS_MARKER])?$options[self::OSS_MARKER]:'',
+ );
+ return $this->auth($options);
+ }
+
+ /**
+ * 创建目录(目录和文件的区别在于,目录最后增加'/')
+ * @param string $bucket (Required)
+ * @param string $object (Required)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function create_object_dir($bucket, $object, $options = NULL){
+ $this->precheck_common($bucket, $object, $options);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_OBJECT] = $object . '/'; //虚拟目录需要以'/结尾'
+ $options[self::OSS_CONTENT_LENGTH] = array(self::OSS_CONTENT_LENGTH => 0);
+ return $this->auth($options);
+ }
+
+ /**
+ * 通过在http body中添加内容来上传文件,适合比较小的文件
+ * 根据api约定,需要在http header中增加content-length字段
+ * @param string $bucket (Required)
+ * @param string $object (Required)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function upload_file_by_content($bucket, $object, $options = NULL){
+ $this->precheck_common($bucket, $object, $options);
+
+ //内容校验
+ OSSUtil::validate_content($options);
+ $content_type = $this->get_mime_type($object);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_OBJECT] = $object;
+
+ if(!isset($options[self::OSS_LENGTH])){
+ $options[self::OSS_CONTENT_LENGTH] = strlen($options[self::OSS_CONTENT]);
+ }else{
+ $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
+ }
+
+ if(!isset($options[self::OSS_CONTENT_TYPE]) && isset($content_type) && !empty($content_type)){
+ $options[self::OSS_CONTENT_TYPE] = $content_type;
+ }
+ return $this->auth($options);
+ }
+
+ /**
+ * 上传文件,适合比较大的文件
+ * @throws OSS_Exception
+ * @param string $bucket (Required)
+ * @param string $object (Required)
+ * @param string $file (Required)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2012-02-28
+ * @return ResponseCore
+ */
+ public function upload_file_by_file($bucket, $object, $file, $options = NULL){
+ $this->precheck_common($bucket, $object, $options);
+ OSSUtil::is_empty($file, OSS_FILE_PATH_IS_NOT_ALLOWED_EMPTY);
+ //Windows系统下进行转码
+ $file = OSSUtil::encoding_path($file);
+ $options[self::OSS_FILE_UPLOAD] = $file;
+ if(!file_exists($options[self::OSS_FILE_UPLOAD])){
+ throw new OSS_Exception($options[self::OSS_FILE_UPLOAD].OSS_FILE_NOT_EXIST);
+ }
+ $file_size = filesize($options[self::OSS_FILE_UPLOAD]);
+ $is_check_md5 = $this->is_check_md5($options);
+ if ($is_check_md5){
+ $content_md5 = base64_encode(md5_file($options[self::OSS_FILE_UPLOAD], true));
+ $options[self::OSS_CONTENT_MD5] = $content_md5;
+ }
+ $content_type = $this->get_mime_type($file);
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_OBJECT] = $object;
+ $options[self::OSS_CONTENT_TYPE] = $content_type;
+ $options[self::OSS_CONTENT_LENGTH] = $file_size;
+ $response = $this->auth($options);
+ return $response;
+ }
+
+ /**
+ * 拷贝object
+ * @param string $from_bucket (Required)
+ * @param string $from_object (Required)
+ * @param string $to_bucket (Required)
+ * @param string $to_object (Required)
+ * @param array $options (Optional)
+ * @return ResponseCore
+ * @throws OSS_Exception
+ */
+ public function copy_object($from_bucket, $from_object, $to_bucket, $to_object, $options = NULL){
+ $this->precheck_common($from_bucket, $from_object, $options);
+ $this->precheck_common($to_bucket, $to_object, $options);
+ $options[self::OSS_BUCKET] = $to_bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_OBJECT] = $to_object;
+ if(isset($options[self::OSS_HEADERS])){
+ $options[self::OSS_HEADERS][self::OSS_OBJECT_COPY_SOURCE] = '/'.$from_bucket.'/'.$from_object;
+ }
+ else {
+ $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_COPY_SOURCE => '/'.$from_bucket.'/'.$from_object);
+ }
+
+ return $this->auth($options);
+ }
+
+ /**
+ * 获得object的meta信息
+ * @param string $bucket (Required)
+ * @param string $object (Required)
+ * @param string $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function get_object_meta($bucket, $object, $options = NULL){
+ $this->precheck_common($bucket, $object, $options);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_HEAD;
+ $options[self::OSS_OBJECT] = $object;
+ return $this->auth($options);
+ }
+
+ /**
+ * 删除object
+ * @param string $bucket(Required)
+ * @param string $object (Required)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function delete_object($bucket, $object, $options = NULL){
+ $this->precheck_common($bucket, $object, $options);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+ $options[self::OSS_OBJECT] = $object;
+ return $this->auth($options);
+ }
+
+ /**
+ * 批量删除objects
+ * @throws OSS_Exception
+ * @param string $bucket(Required)
+ * @param array $objects (Required)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2012-03-09
+ * @return ResponseCore
+ */
+ public function delete_objects($bucket, $objects, $options = null){
+ $this->precheck_common($bucket, NULL, $options, false);
+ //objects
+ if(!is_array($objects) || !$objects){
+ throw new OSS_Exception('The ' . __FUNCTION__ . ' method requires the "objects" option to be set as an array.');
+ }
+
+ $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'delete';
+ $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+ $xml = new SimpleXMLElement('');
+ // Quiet mode
+ if (isset($options['quiet'])){
+ $quiet = 'false';
+ if (is_bool($options['quiet'])) { //Boolean
+ $quiet = $options['quiet'] ? 'true' : 'false';
+ }elseif (is_string($options['quiet'])){ // String
+ $quiet = ($options['quiet'] === 'true') ? 'true' : 'false';
+ }
+ $xml->addChild('Quiet', $quiet);
+ }
+ // Add the objects
+ foreach ($objects as $object){
+ $sub_object = $xml->addChild('Object');
+ $object = OSSUtil::s_replace($object);
+ $sub_object->addChild('Key', $object);
+ }
+ $options[self::OSS_CONTENT] = $xml->asXML();
+ return $this->auth($options);
+ }
+
+ /**
+ * 获得Object内容
+ * @param string $bucket(Required)
+ * @param string $object (Required)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function get_object($bucket, $object, $options = NULL){
+ $this->precheck_common($bucket, $object, $options);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_OBJECT] = $object;
+ if(isset($options[self::OSS_LAST_MODIFIED])){
+ $options[self::OSS_HEADERS][self::OSS_IF_MODIFIED_SINCE] = $options[self::OSS_LAST_MODIFIED];
+ unset($options[self::OSS_LAST_MODIFIED]);
+ }
+ if(isset($options[self::OSS_ETAG])){
+ $options[self::OSS_HEADERS][self::OSS_IF_NONE_MATCH] = $options[self::OSS_ETAG];
+ unset($options[self::OSS_ETAG]);
+ }
+ if(isset($options[self::OSS_RANGE])){
+ $range = $options[self::OSS_RANGE];
+ $options[self::OSS_HEADERS][self::OSS_RANGE] = "bytes=$range";
+ unset($options[self::OSS_RANGE]);
+ }
+
+ return $this->auth($options);
+ }
+
+ /**
+ * 检测Object是否存在
+ * @param string $bucket(Required)
+ * @param string $object (Required)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function is_object_exist($bucket, $object, $options = NULL){
+ return $this->get_object_meta($bucket, $object, $options);
+ }
+
+ /**
+ * 获取分片大小
+ * @param int $part_size (Required)
+ * @return int
+ */
+ private function get_part_size($part_size){
+ $part_size = (integer)$part_size;
+ if($part_size <= self::OSS_MIN_PART_SIZE){
+ $part_size = self::OSS_MIN_PART_SIZE;
+ }elseif ($part_size > self::OSS_MAX_PART_SIZE){
+ $part_size = self::OSS_MAX_PART_SIZE;
+ }else{
+ $part_size = self::OSS_MID_PART_SIZE;
+ }
+ return $part_size;
+ }
+
+ /*%******************************************************************************************************%*/
+ //Multi Part相关操作
+ /**
+ * 计算文件可以分成多少个part,以及每个part的长度以及起始位置
+ * 方法必须在 中调用
+ *
+ * @param integer $file_size (Required) 文件大小
+ * @param integer $part_size (Required) part大小,默认5M
+ * @return array An array 包含 key-value 键值对. Key 为 `seekTo` 和 `length`.
+ */
+ public function get_multipart_counts($file_size, $part_size = 5242880){
+ $i = 0;
+ $size_count = $file_size;
+ $values = array();
+ $part_size = $this->get_part_size($part_size);
+ while ($size_count > 0)
+ {
+ $size_count -= $part_size;
+ $values[] = array(
+ self::OSS_SEEK_TO => ($part_size * $i),
+ self::OSS_LENGTH => (($size_count > 0) ? $part_size : ($size_count + $part_size)),
+ );
+ $i++;
+ }
+ return $values;
+ }
+
+ /**
+ * 初始化multi-part upload
+ * @param string $bucket (Required) Bucket名称
+ * @param string $object (Required) Object名称
+ * @param array $options (Optional) Key-Value数组
+ * @return ResponseCore
+ */
+ public function initiate_multipart_upload($bucket, $object, $options = NULL){
+ $this->precheck_common($bucket, $object, $options);
+ $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_OBJECT] = $object;
+ $options[self::OSS_SUB_RESOURCE] = 'uploads';
+ $options[self::OSS_CONTENT] = '';
+ $content_type = $this->get_mime_type($object);
+ if(!isset($options[self::OSS_HEADERS])){
+ $options[self::OSS_HEADERS] = array();
+ }
+ $options[self::OSS_HEADERS][self::OSS_CONTENT_TYPE] = $content_type;
+
+ return $this->auth($options);
+ }
+
+ /**
+ * 初始化multi-part upload,并且返回uploadId
+ * @param string $bucket (Required) Bucket名称
+ * @param string $object (Required) Object名称
+ * @param array $options (Optional) Key-Value数组
+ * @return string uploadId
+ * @throws OSS_Exception
+ */
+ public function init_multipart_upload($bucket, $object, $options = NULL){
+ $res = $this->initiate_multipart_upload($bucket, $object, $options);
+ if (!$res->isOK()){
+ throw new OSS_Exception('Init multi-part upload failed...');
+ }
+ $xml = new SimpleXmlIterator($res->body);
+ $uploadId = (string)$xml->UploadId;
+ return $uploadId;
+ }
+
+ /**
+ * 上传part
+ * @param string $bucket (Required) Bucket名称
+ * @param string $object (Required) Object名称
+ * @param string $upload_id (Required) uploadId
+ * @param array $options (Optional) Key-Value数组
+ * @return ResponseCore
+ */
+ public function upload_part($bucket, $object, $upload_id, $options = null){
+ $this->precheck_common($bucket, $object, $options);
+ $this->precheck_param($options, self::OSS_FILE_UPLOAD, __FUNCTION__);
+ $this->precheck_param($options, self::OSS_PART_NUM, __FUNCTION__);
+
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_OBJECT] = $object;
+ $options[self::OSS_UPLOAD_ID] = $upload_id;
+
+ if(isset($options[self::OSS_LENGTH])){
+ $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
+ }
+ return $this->auth($options);
+ }
+
+ /**
+ * 获取已成功上传的part
+ * @param string $bucket (Required) Bucket名称
+ * @param string $object (Required) Object名称
+ * @param string $upload_id (Required) uploadId
+ * @param array $options (Optional) Key-Value数组
+ * @return ResponseCore
+ */
+ public function list_parts($bucket, $object, $upload_id, $options = null){
+ $this->precheck_common($bucket, $object, $options);
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_OBJECT] = $object;
+ $options[self::OSS_UPLOAD_ID] = $upload_id;
+ $options[self::OSS_QUERY_STRING] = array();
+ foreach (array('max-parts', 'part-number-marker') as $param){
+ if (isset($options[$param])){
+ $options[self::OSS_QUERY_STRING][$param] = $options[$param];
+ unset($options[$param]);
+ }
+ }
+ return $this->auth($options);
+ }
+
+ /**
+ * 中止上传mulit-part upload
+ * @param string $bucket (Required) Bucket名称
+ * @param string $object (Required) Object名称
+ * @param string $upload_id (Required) uploadId
+ * @param array $options (Optional) Key-Value数组
+ * @return ResponseCore
+ */
+ public function abort_multipart_upload($bucket, $object, $upload_id, $options = NULL){
+ $this->precheck_common($bucket, $object, $options);
+ $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_OBJECT] = $object;
+ $options[self::OSS_UPLOAD_ID] = $upload_id;
+ return $this->auth($options);
+ }
+
+ /**
+ * 完成multi-part上传
+ * @param string $bucket (Required) Bucket名称
+ * @param string $object (Required) Object名称
+ * @param string $upload_id (Required) uploadId
+ * @param array | xml $parts 可以是一个上传成功part的数组,或者是一个ReponseCore对象
+ * @param array $options (Optional) Key-Value数组
+ * @return ResponseCore
+ */
+ public function complete_multipart_upload($bucket, $object, $upload_id, $parts, $options = NULL){
+ $this->precheck_common($bucket, $object, $options);
+ $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_OBJECT] = $object;
+ $options[self::OSS_UPLOAD_ID] = $upload_id;
+ $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+
+ if(is_string($parts)){
+ $options[self::OSS_CONTENT] = $parts;
+ }else if($parts instanceof SimpleXMLElement){
+ $options[self::OSS_CONTENT] = $parts->asXML();
+ }else if((is_array($parts) || $parts instanceof ResponseCore)){
+ $xml = new SimpleXMLElement('');
+
+ if (is_array($parts)){
+ foreach ($parts as $node){
+ $part = $xml->addChild('Part');
+ $part->addChild('PartNumber', $node['PartNumber']);
+ $part->addChild('ETag', $node['ETag']);
+ }
+ }elseif ($parts instanceof ResponseCore){
+ foreach ($parts->body->Part as $node){
+ $part = $xml->addChild('Part');
+ $part->addChild('PartNumber', (string) $node->PartNumber);
+ $part->addChild('ETag', (string) $node->ETag);
+ }
+ }
+ $options[self::OSS_CONTENT] = $xml->asXML();
+ }
+ return $this->auth($options);
+ }
+
+ /**
+ * 列出multipart上传
+ * @param string $bucket (Requeired) bucket
+ * @param array $options (Optional) 关联数组
+ * @author xiaobing
+ * @since 2012-03-05
+ * @return ResponseCore
+ */
+ public function list_multipart_uploads($bucket, $options = null){
+ $this->precheck_common($bucket, NULL, $options, false);
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_OBJECT] = '/';
+ $options[self::OSS_SUB_RESOURCE] = 'uploads';
+
+ foreach (array('delimiter','key-marker', 'max-uploads', 'prefix','upload-id-marker') as $param){
+ if (isset($options[$param])){
+ $options[self::OSS_QUERY_STRING][$param] = $options[$param];
+ unset($options[$param]);
+ }
+ }
+ return $this->auth($options);
+ }
+
+ /**
+ * 从已存在的object拷贝part
+ * @param string $from_bucket (Required)
+ * @param string $from_object (Required)
+ * @param string $to_bucket (Required)
+ * @param string $to_object (Required)
+ * @param int $part_number (Required)
+ * @param string $upload_id (Required)
+ * @param array $options (Optional) Key-Value数组
+ * @return ResponseCore
+ * @throws OSS_Exception
+ */
+ public function copy_upload_part($from_bucket, $from_object, $to_bucket, $to_object, $part_number, $upload_id, $options = NULL){
+ $this->precheck_common($from_bucket, $from_object, $options);
+ $this->precheck_common($to_bucket, $to_object, $options);
+
+ //如果没有设置$options['isFullCopy'],则需要强制判断copy的起止位置
+ $start_range = "0";
+ if(isset($options['start'])){
+ $start_range = $options['start'];
+ }
+ $end_range = "";
+ if(isset($options['end'])){
+ $end_range = $options['end'];
+ }
+ $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+ $options[self::OSS_BUCKET] = $to_bucket;
+ $options[self::OSS_OBJECT] = $to_object;
+ $options[self::OSS_PART_NUM] = $part_number;
+ $options[self::OSS_UPLOAD_ID] = $upload_id;
+
+ if(!isset($options[self::OSS_HEADERS])){
+ $options[self::OSS_HEADERS] = array();
+ }
+
+ $options[self::OSS_HEADERS][self::OSS_OBJECT_COPY_SOURCE] = '/' . $from_bucket . '/' . $from_object;
+ $options[self::OSS_HEADERS][self::OSS_OBJECT_COPY_SOURCE_RANGE] = "bytes=" . $start_range . "-" . $end_range;
+ return $this->auth($options);
+ }
+
+ /**
+ * multipart上传统一封装,从初始化到完成multipart,以及出错后中止动作
+ * @param string $bucket (Required)
+ * @param string $object (Required)
+ * @param array $options (Optional) Key-Value数组
+ * @return ResponseCore
+ * @throws OSS_Exception
+ */
+ public function create_mpu_object($bucket, $object, $options = null){
+ $this->precheck_common($bucket, $object, $options);
+ if(isset($options[self::OSS_LENGTH])){
+ $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
+ unset($options[self::OSS_LENGTH]);
+ }
+
+ if(isset($options[self::OSS_FILE_UPLOAD])){
+ //Windows系统下进行转码
+ $options[self::OSS_FILE_UPLOAD] = OSSUtil::encoding_path($options[self::OSS_FILE_UPLOAD]);
+ }
+
+ $this->precheck_param($options, self::OSS_FILE_UPLOAD, __FUNCTION__);
+ $upload_position = isset($options[self::OSS_SEEK_TO]) ? (integer) $options[self::OSS_SEEK_TO] : 0;
+
+ if (isset($options[self::OSS_CONTENT_LENGTH])){
+ $upload_file_size = (integer) $options[self::OSS_CONTENT_LENGTH];
+ } else {
+ $filename = $options[self::OSS_FILE_UPLOAD];
+ $upload_file_size = filesize($filename);
+ if ($upload_file_size !== false) {
+ $upload_file_size -= $upload_position;
+ }
+ }
+
+ if ($upload_position === false || !isset($upload_file_size) || $upload_file_size === false || $upload_file_size < 0){
+ throw new OSS_Exception('The size of `fileUpload` cannot be determined in ' . __FUNCTION__ . '().');
+ }
+ // 处理partSize
+ if (isset($options[self::OSS_PART_SIZE])){
+ $options[self::OSS_PART_SIZE] = $this->get_part_size($options[self::OSS_PART_SIZE]);
+ }
+ else{
+ $options[self::OSS_PART_SIZE] = self::OSS_MID_PART_SIZE;
+ }
+
+ $is_check_md5 = $this->is_check_md5($options);
+ // 如果上传的文件小于partSize,则直接使用普通方式上传
+ if ($upload_file_size < $options[self::OSS_PART_SIZE] && !isset($options[self::OSS_UPLOAD_ID])){
+ $local_file = $options[self::OSS_FILE_UPLOAD];
+ $options = array(
+ self::OSS_CHECK_MD5 => $is_check_md5,
+ );
+ return $this->upload_file_by_file($bucket, $object, $local_file, $options);
+ }
+
+ // 初始化multipart
+ if (isset($options[self::OSS_UPLOAD_ID])){
+ $upload_id = $options[self::OSS_UPLOAD_ID];
+ }else{
+ //初始化
+ $init_options = array();
+ $upload_id = $this->init_multipart_upload($bucket, $object, $init_options);
+ }
+
+ // 获取的分片
+ $pieces = $this->get_multipart_counts($upload_file_size, (integer) $options[self::OSS_PART_SIZE]);
+
+ $response_upload_part = array();
+ foreach ($pieces as $i => $piece){
+ $from_pos = $upload_position + (integer) $piece[self::OSS_SEEK_TO];
+ $to_pos = (integer) $piece[self::OSS_LENGTH] + $from_pos - 1;
+ $up_options = array(
+ self::OSS_FILE_UPLOAD => $options[self::OSS_FILE_UPLOAD],
+ self::OSS_PART_NUM => ($i + 1),
+ self::OSS_SEEK_TO => $from_pos,
+ self::OSS_LENGTH => $to_pos - $from_pos + 1,
+ self::OSS_CHECK_MD5 => $is_check_md5,
+ );
+ if ($is_check_md5) {
+ $content_md5 = OSSUtil::get_content_md5_of_file($options[self::OSS_FILE_UPLOAD], $from_pos, $to_pos);
+ $up_options[self::OSS_CONTENT_MD5] = $content_md5;
+ }
+ $response_upload_part[] = $this->upload_part($bucket, $object, $upload_id, $up_options);
+ }
+
+ $upload_parts = array();
+ $upload_part_result = true;
+ foreach ($response_upload_part as $i => $response){
+ $upload_part_result = $upload_part_result && $response->isOk();
+ if(!$upload_part_result){
+ throw new OSS_Exception('any part upload failed, please try again');
+ }
+ $upload_parts[] = array(
+ 'PartNumber' => ($i + 1),
+ 'ETag' => (string) $response->header['etag']
+ );
+ }
+ return $this->complete_multipart_upload($bucket, $object, $upload_id, $upload_parts);
+ }
+
+ /**
+ * 通过Multi-Part方式上传整个目录,其中的object默认为文件名
+ * @param string $bucket (Required)
+ * @param string $dir (Required)
+ * @param bool $recursive 是否递归,如果为true,则递归读取所有目录,默认为不递归读取
+ * @param string $exclude
+ * @param array $options (Optional) Key-Value数组,其中可以包括以下的key
+ * @return bool
+ * @throws OSS_Exception
+ */
+ public function create_mtu_object_by_dir($bucket, $dir, $recursive = false, $exclude = ".|..|.svn", $options = null){
+ $this->precheck_common($bucket, NULL, $options, false);
+ //Windows系统下进行转码
+ $dir = OSSUtil::encoding_path($dir);
+ //判断是否目录
+ if(!is_dir($dir)){
+ throw new OSS_Exception($dir.' is not a directory, please check it');
+ }
+
+ $file_list_array = $this->read_dir($dir, $exclude, $recursive);
+
+
+ if(empty($file_list_array)){
+ throw new OSS_Exception($dir.' is empty...');
+ }
+
+ $is_upload_ok = true;
+ $index = 1;
+
+ foreach ($file_list_array as $k=>$item){
+ echo $index++.". ";
+ echo "Multiupload file ".$item['path']." ";
+ if (is_dir($item['path'])) {
+ echo " skipped, because it is directory...\n";
+ }
+ else {
+ $options = array(
+ self::OSS_FILE_UPLOAD => $item['path'],
+ self::OSS_PART_SIZE => self::OSS_MIN_PART_SIZE,
+ );
+
+ $response = $this->create_mpu_object($bucket, $item['file'], $options);
+ if($response->isOK()){
+ echo " successful..\n";
+ }
+ else {
+ echo " failed..\n";
+ $is_upload_ok = false;
+ continue;
+ }
+ }
+ }
+ return $is_upload_ok;
+ }
+
+ /**
+ * 上传目录
+ * @param array $options
+ * $options = array(
+ * 'bucket' => (Required) string
+ * 'object' => (Optional) string
+ * 'directory' => (Required) string
+ * 'exclude' => (Optional) string
+ * 'recursive' => (Optional) string
+ * 'checkmd5' => (Optional) boolean
+ * )
+ * @return bool
+ * @throws OSS_Exception
+ */
+ public function batch_upload_file($options = NULL){
+ if((NULL == $options) || !isset($options['bucket']) || empty($options['bucket']) || !isset($options['directory']) ||empty($options['directory'])){
+ throw new OSS_Exception('Bad Request', 400);
+ }
+
+ $is_batch_upload_ok = true;
+ $bucket = $this->get_value($options, 'bucket');
+ $directory = $this->get_value($options, 'directory');
+ //Windows系统下进行转码
+ $directory = OSSUtil::encoding_path($directory);
+
+ //判断是否目录
+ if(!is_dir($directory)){
+ throw new OSS_Exception($directory . ' is not a directory, please check it');
+ }
+
+ $object = $this->get_value($options, 'object', '');
+ $exclude = $this->get_value($options, 'exclude', '.|..|.svn', true);
+ $recursive = $this->get_value($options, 'recursive', false, true, true);
+
+ //read directory
+ $file_list_array = $this->read_dir($directory, $exclude, $recursive);
+
+ if(!$file_list_array){
+ throw new OSS_Exception($directory.' is empty...');
+ }
+
+ $index = 1;
+ $is_check_md5 = $this->is_check_md5($options);
+
+ foreach ($file_list_array as $k=>$item){
+ echo $index++.". ";
+ echo "Upload file ".$item['path']." ";
+ if (is_dir($item['path'])) {
+ echo " skipped, because it is directory...\n";
+ }
+ else {
+ $options = array(
+ self::OSS_FILE_UPLOAD => $item['path'],
+ self::OSS_PART_SIZE => self::OSS_MIN_PART_SIZE,
+ self::OSS_CHECK_MD5 => $is_check_md5,
+ );
+ $real_object = (!empty($object)?$object.'/':'').$item['file'];
+ $response = $this->create_mpu_object($bucket, $real_object, $options);
+ if($response->isOK()){
+ echo " successful..\n";
+ }else{
+ echo " failed..\n";
+ $is_batch_upload_ok = false;
+ continue;
+ }
+ }
+ }
+ return $is_batch_upload_ok;
+ }
+
+ /*%******************************************************************************************************%*/
+ //Object Group相关操作, 不建议再使用,官方API文档中已经无相关介绍
+ /**
+ * 转化object数组为固定个xml格式
+ * @param string $bucket (Required)
+ * @param array $object_array (Required)
+ * @throws OSS_Exception
+ * @author xiaobing
+ * @since 2011-12-27
+ * @return string
+ */
+ public function make_object_group_xml($bucket, $object_array){
+ $xml = '';
+ $xml .= '';
+
+ if($object_array){
+ if(count($object_array) > self::OSS_MAX_OBJECT_GROUP_VALUE){
+ throw new OSS_Exception(OSS_OBJECT_GROUP_TOO_MANY_OBJECT, '-401');
+ }
+ $index = 1;
+ foreach ($object_array as $key => $value){
+ $object_meta = (array)$this->get_object_meta($bucket, $value);
+ if(isset($object_meta) && isset($object_meta['status']) && isset($object_meta['header']) && isset($object_meta['header']['etag']) && $object_meta['status'] == 200){
+ $xml .= '';
+ $xml .= ''.intval($index).'';
+ $xml .= ''.$value.'';
+ $xml .= ''.$object_meta['header']['etag'].'';
+ $xml .= '';
+
+ $index++;
+ }
+ }
+ }else{
+ throw new OSS_Exception(OSS_OBJECT_ARRAY_IS_EMPTY, '-400');
+ }
+ $xml .= '';
+ return $xml;
+ }
+ /**
+ * 创建Object Group, 不建议再使用,官方API文档中已经无相关介绍
+ * @param string $object_group (Required) Object Group名称
+ * @param string $bucket (Required) Bucket名称
+ * @param array $object_arry (Required) object数组,所有的object必须在同一个bucket下
+ * 其中$object_arrya 格式如下:
+ * $object = array(
+ * $object1,
+ * $object2,
+ * ...
+ * )
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function create_object_group($bucket, $object_group, $object_arry, $options = NULL){
+ $this->precheck_common($bucket, $object_group, $options);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+ $options[self::OSS_OBJECT] = $object_group;
+ $options[self::OSS_CONTENT_TYPE] = $this->get_mime_type($object_group); //重设Content-Type
+ $options[self::OSS_SUB_RESOURCE] = 'group'; //设置?group
+ $options[self::OSS_CONTENT] = $this->make_object_group_xml($bucket, $object_arry); //格式化xml
+ return $this->auth($options );
+ }
+
+ /**
+ * 获取Object Group, 不建议再使用,官方API文档中已经无相关介绍
+ * @param string $object_group (Required)
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function get_object_group($bucket, $object_group, $options = NULL){
+ $this->precheck_common($bucket, $object_group, $options);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_OBJECT] = $object_group;
+ $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_GROUP => self::OSS_OBJECT_GROUP); //header中的x-oss-file-group不能为空,否则返回值错误
+ return $this->auth($options);
+ }
+
+ /**
+ * 获取Object Group 的Object List信息, 不建议再使用,官方API文档中已经无相关介绍
+ * @param string $object_group (Required)
+ * @param string $bucket (Required)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function get_object_group_index($bucket, $object_group, $options = NULL){
+ $this->precheck_common($bucket, $object_group, $options);
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+ $options[self::OSS_OBJECT] = $object_group;
+ $options[self::OSS_CONTENT_TYPE] = 'application/xml'; //重设Content-Type
+ $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_GROUP => self::OSS_OBJECT_GROUP);
+ return $this->auth($options);
+ }
+
+ /**
+ * 获得object group的meta信息, 不建议再使用,官方API文档中已经无相关介绍
+ * @param string $bucket (Required)
+ * @param string $object_group (Required)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function get_object_group_meta($bucket, $object_group, $options = NULL){
+ return $this->get_object_meta($bucket, $object_group, $options);
+ }
+
+ /**
+ * 删除Object Group, 不建议再使用,官方API文档中已经无相关介绍
+ * @param string $bucket(Required)
+ * @param string $object_group (Required)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-11-14
+ * @return ResponseCore
+ */
+ public function delete_object_group($bucket, $object_group, $options = NULL){
+ return $this->delete_object($bucket, $object_group, $options);
+ }
+
+ /*%******************************************************************************************************%*/
+ //带签名的url相关
+
+ /**
+ * 获取GET签名的url
+ * @param string $bucket (Required)
+ * @param string $object (Required)
+ * @param int $timeout (Optional)
+ * @param array $options (Optional)
+ * @author xiaobing
+ * @since 2011-12-21
+ * @return string
+ */
+ public function get_sign_url($bucket, $object, $timeout = 60, $options = NULL){
+ return $this->presign_url($bucket, $object, $timeout, self::OSS_HTTP_GET, $options);
+ }
+
+ /**
+ * 获取签名url,支持生成get和put签名
+ * @param string $bucket
+ * @param string $object
+ * @param int $timeout
+ * @param array $options (Optional) Key-Value数组
+ * @param string $method
+ * @return ResponseCore
+ * @throws OSS_Exception
+ */
+ public function presign_url($bucket, $object, $timeout = 60, $method = self::OSS_HTTP_GET, $options = NULL){
+ $this->precheck_common($bucket, $object, $options);
+ //method
+ if (self::OSS_HTTP_GET !== $method && self::OSS_HTTP_PUT !== $method) {
+ throw new OSS_Exception(OSS_INVALID_METHOD);
+ }
+ $options[self::OSS_BUCKET] = $bucket;
+ $options[self::OSS_OBJECT] = $object;
+ $options[self::OSS_METHOD] = $method;
+ if (!isset($options[self::OSS_CONTENT_TYPE])) {
+ $options[self::OSS_CONTENT_TYPE] = '';
+ }
+ $timeout = time() + $timeout;
+ $options[self::OSS_PREAUTH] = $timeout;
+ $options[self::OSS_DATE] = $timeout;
+ $this->set_sign_sts_in_url(true);
+ return $this->auth($options);
+ }
+
+ /**
+ * 检测options参数
+ * @param array $options
+ * @throws OSS_Exception
+ */
+ private function precheck_options(&$options) {
+ OSSUtil::validate_options($options);
+ if (!$options) {
+ $options = array();
+ }
+ }
+
+ /**
+ * 校验bucket参数
+ * @param string $bucket
+ * @param string $err_msg
+ * @throws OSS_Exception
+ */
+ private function precheck_bucket($bucket, $err_msg = OSS_BUCKET_IS_NOT_ALLOWED_EMPTY) {
+ OSSUtil::is_empty($bucket, $err_msg);
+ }
+
+ /**
+ * 校验object参数
+ * @param string $object
+ * @throws OSS_Exception
+ */
+ private function precheck_object($object) {
+ OSSUtil::is_empty($object, OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
+ }
+
+ /**
+ * 校验bucket,options参数
+ * @param string $bucket
+ * @param string $object
+ * @param array $options
+ * @param bool $is_check_object
+ */
+ private function precheck_common($bucket, $object, &$options, $is_check_object = true) {
+ if ($is_check_object){
+ $this->precheck_object($object);
+ }
+ $this->precheck_options($options);
+ $this->precheck_bucket($bucket);
+ }
+
+ /**
+ * 参数校验
+ * @param array $options
+ * @param string $param
+ * @param string $func_name
+ * @throws OSS_Exception
+ */
+ private function precheck_param($options, $param, $func_name){
+ if (!isset($options[$param])){
+ throw new OSS_Exception('The `' . $param . '` options is required in ' . $func_name . '().');
+ }
+ }
+
+ /**
+ * 检测md5
+ * @param array $options
+ * @return bool|null
+ */
+ private function is_check_md5($options){
+ return $this->get_value($options, self::OSS_CHECK_MD5, false, true, true);
+ }
+
+ /**
+ * 获取value
+ * @param array $options
+ * @param string $key
+ * @param string $default
+ * @param bool $is_check_empty
+ * @param bool $is_check_bool
+ * @return bool|null
+ */
+ private function get_value($options, $key, $default = NULL, $is_check_empty = false, $is_check_bool = false) {
+ $value = $default;
+ if (isset($options[$key])){
+ if ($is_check_empty){
+ if (!empty($options[$key])){
+ $value= $options[$key];
+ }
+ }
+ else{
+ $value= $options[$key];
+ }
+ unset($options[$key]);
+ }
+ if ($is_check_bool){
+ if ($value !== true && $value !== false){
+ $value = false;
+ }
+ }
+ return $value;
+ }
+
+ /**
+ * 获取mimetype类型
+ * @param string $object
+ * @return string
+ */
+ private function get_mime_type($object) {
+ $extension = explode('.', $object);
+ $extension = array_pop($extension);
+ $mime_type = MimeTypes::get_mimetype(strtolower($extension));
+ return $mime_type;
+ }
+
+ /**
+ * 读取目录
+ * @param $dir
+ * @param string $exclude
+ * @param bool $recursive
+ * @return array
+ */
+ private function read_dir($dir, $exclude = ".|..|.svn", $recursive = false){
+ $file_list_array = array();
+ $base_path=$dir;
+ $exclude_array = explode("|", $exclude);
+ // filter out "." and ".."
+ $exclude_array = array_unique(array_merge($exclude_array,array('.','..')));
+
+ if($recursive){
+ foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $new_file)
+ {
+ if ($new_file->isDir()) continue;
+ echo "$new_file\n";
+ $object = str_replace($base_path, '', $new_file);
+ if(!in_array(strtolower($object), $exclude_array)){
+ $object = ltrim($object, '/');
+ if (is_file($new_file)){
+ $key = md5($new_file.$object, false);
+ $file_list_array[$key] = array('path' => $new_file,'file' => $object,);
+ }
+ }
+ }
+ }
+ else if($handle = opendir($dir)){
+ while ( false !== ($file = readdir($handle))){
+ if(!in_array(strtolower($file), $exclude_array)){
+ $new_file = $dir.'/'.$file;
+
+ $object = $file;
+ $object = ltrim($object, '/');
+ if (is_file($new_file)){
+ $key = md5($new_file.$object, false);
+ $file_list_array[$key] = array('path' => $new_file,'file' => $object,);
+ }
+ }
+ }
+ closedir($handle);
+ }
+ return $file_list_array;
+ }
+
+
+ /*%******************************************************************************************************%*/
+ //请求
+
+ /**
+ * auth接口
+ * @param array $options
+ * @return ResponseCore
+ * @throws OSS_Exception
+ * @throws RequestCore_Exception
+ */
+ public function auth($options){
+ OSSUtil::validate_options($options);
+
+ //验证Bucket,list_bucket时不需要验证
+ if(!( ('/' == $options[self::OSS_OBJECT]) && ('' == $options[self::OSS_BUCKET]) && ('GET' == $options[self::OSS_METHOD])) && !OSSUtil::validate_bucket($options[self::OSS_BUCKET])){
+ throw new OSS_Exception('"'.$options[self::OSS_BUCKET].'"'.OSS_BUCKET_NAME_INVALID);
+ }
+ //验证Object
+ if(isset($options[self::OSS_OBJECT]) && !OSSUtil::validate_object($options[self::OSS_OBJECT])){
+ throw new OSS_Exception($options[self::OSS_OBJECT].OSS_OBJECT_NAME_INVALID);
+ }
+ //Object编码为UTF-8
+ $tmp_object = $options[self::OSS_OBJECT];
+ try {
+ if(OSSUtil::is_gb2312($options[self::OSS_OBJECT])){
+ $options[self::OSS_OBJECT] = iconv('GB2312', "UTF-8//IGNORE",$options[self::OSS_OBJECT]);
+ }elseif(OSSUtil::check_char($options[self::OSS_OBJECT],true)){
+ $options[self::OSS_OBJECT] = iconv('GBK', "UTF-8//IGNORE",$options[self::OSS_OBJECT]);
+ }
+ } catch (Exception $e) {
+ try{
+ $tmp_object = iconv(mb_detect_encoding($tmp_object), "UTF-8", $tmp_object);
+ }
+ catch(Exception $e) {
+ }
+ }
+ $options[self::OSS_OBJECT] = $tmp_object;
+
+ //验证ACL
+ if(isset($options[self::OSS_HEADERS][self::OSS_ACL]) && !empty($options[self::OSS_HEADERS][self::OSS_ACL])){
+ if(!in_array(strtolower($options[self::OSS_HEADERS][self::OSS_ACL]), self::$OSS_ACL_TYPES)){
+ throw new OSS_Exception($options[self::OSS_HEADERS][self::OSS_ACL].':'.OSS_ACL_INVALID);
+ }
+ }
+
+ //定义scheme
+ $scheme = $this->use_ssl ? 'https://' : 'http://';
+ if($this->enable_domain_style){
+ $hostname = $this->vhost ? $this->vhost : (($options[self::OSS_BUCKET] == '') ? $this->hostname : ($options[self::OSS_BUCKET].'.').$this->hostname);
+ }else{
+ $hostname = (isset($options[self::OSS_BUCKET]) && '' !== $options[self::OSS_BUCKET]) ? $this->hostname.'/'.$options[self::OSS_BUCKET] : $this->hostname;
+ }
+
+ //请求参数
+ $signable_resource = '';
+ $query_string_params = array();
+ $signable_query_string_params = array();
+ $string_to_sign = '';
+
+ $oss_host = $this->hostname;
+ if ($this->enable_domain_style){
+ $oss_host = $hostname;
+ }
+ $headers = array (
+ self::OSS_CONTENT_MD5 => '',
+ self::OSS_CONTENT_TYPE => isset($options[self::OSS_CONTENT_TYPE]) ? $options[self::OSS_CONTENT_TYPE] : 'application/x-www-form-urlencoded',
+ self::OSS_DATE => isset($options[self::OSS_DATE]) ? $options[self::OSS_DATE] : gmdate('D, d M Y H:i:s \G\M\T'),
+ self::OSS_HOST => $oss_host,
+ );
+
+ if (isset($options[self::OSS_CONTENT_MD5])){
+ $headers[self::OSS_CONTENT_MD5] = $options[self::OSS_CONTENT_MD5];
+ }
+
+ //增加stsSecurityToken
+ if((!is_null($this->security_token)) && (!$this->enable_sts_in_url)){
+ $headers[self::OSS_SECURITY_TOKEN] = $this->security_token;
+ }
+
+ if (isset($options[self::OSS_OBJECT]) && '/' !== $options[self::OSS_OBJECT]){
+ $signable_resource = '/'.str_replace(array('%2F', '%25'), array('/', '%'), rawurlencode($options[self::OSS_OBJECT]));
+ }
+
+ if(isset($options[self::OSS_QUERY_STRING])){
+ $query_string_params = array_merge($query_string_params, $options[self::OSS_QUERY_STRING]);
+ }
+ $query_string = OSSUtil::to_query_string($query_string_params);
+
+ $signable_list = array(
+ self::OSS_PART_NUM,
+ 'response-content-type',
+ 'response-content-language',
+ 'response-cache-control',
+ 'response-content-encoding',
+ 'response-expires',
+ 'response-content-disposition',
+ self::OSS_UPLOAD_ID,
+ );
+
+ foreach ($signable_list as $item){
+ if(isset($options[$item])){
+ $signable_query_string_params[$item] = $options[$item];
+ }
+ }
+
+ if ($this->enable_sts_in_url && (!is_null($this->security_token))) {
+ $signable_query_string_params["security-token"] = $this->security_token;
+ }
+ $signable_query_string = OSSUtil::to_query_string($signable_query_string_params);
+
+ //合并 HTTP headers
+ if (isset($options[self::OSS_HEADERS])) {
+ $headers = array_merge($headers, $options[self::OSS_HEADERS]);
+ }
+
+ //生成请求URL
+ $conjunction = '?';
+
+ $non_signable_resource = '';
+
+ if (isset($options[self::OSS_SUB_RESOURCE])){
+ $signable_resource .= $conjunction . $options[self::OSS_SUB_RESOURCE];
+ $conjunction = '&';
+ }
+
+ if($signable_query_string !== ''){
+ $signable_query_string = $conjunction . $signable_query_string;
+ $conjunction = '&';
+ }
+
+ if($query_string !== ''){
+ $non_signable_resource .= $conjunction . $query_string;
+ $conjunction = '&';
+ }
+
+ $this->request_url = $scheme . $hostname . $signable_resource . $signable_query_string . $non_signable_resource;
+
+ //创建请求
+ $request = new RequestCore($this->request_url);
+ $user_agent = OSS_NAME."/".OSS_VERSION." (".php_uname('s')."/".php_uname('r')."/".php_uname('m').";".PHP_VERSION.")";
+ $request->set_useragent($user_agent);
+
+ // Streaming uploads
+ if (isset($options[self::OSS_FILE_UPLOAD])){
+ if (is_resource($options[self::OSS_FILE_UPLOAD])){
+ $length = null;
+
+ if (isset($options[self::OSS_CONTENT_LENGTH])){
+ $length = $options[self::OSS_CONTENT_LENGTH];
+ }elseif (isset($options[self::OSS_SEEK_TO])){
+ $stats = fstat($options[self::OSS_FILE_UPLOAD]);
+ if ($stats && $stats[self::OSS_SIZE] >= 0){
+ $length = $stats[self::OSS_SIZE] - (integer) $options[self::OSS_SEEK_TO];
+ }
+ }
+
+ $request->set_read_stream($options[self::OSS_FILE_UPLOAD], $length);
+
+ if ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded'){
+ $headers[self::OSS_CONTENT_TYPE] = 'application/octet-stream';
+ }
+ }else{
+ $request->set_read_file($options[self::OSS_FILE_UPLOAD]);
+ $length = $request->read_stream_size;
+ if (isset($options[self::OSS_CONTENT_LENGTH])){
+ $length = $options[self::OSS_CONTENT_LENGTH];
+ }elseif (isset($options[self::OSS_SEEK_TO]) && isset($length)){
+ $length -= (integer) $options[self::OSS_SEEK_TO];
+ }
+ $request->set_read_stream_size($length);
+ if (isset($headers[self::OSS_CONTENT_TYPE]) && ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded')){
+ $mime_type = self::get_mime_type($options[self::OSS_FILE_UPLOAD]);
+ $headers[self::OSS_CONTENT_TYPE] = $mime_type;
+ }
+ }
+ }
+
+ if (isset($options[self::OSS_SEEK_TO])){
+ $request->set_seek_position((integer)$options[self::OSS_SEEK_TO]);
+ }
+
+ if (isset($options[self::OSS_FILE_DOWNLOAD])){
+ if (is_resource($options[self::OSS_FILE_DOWNLOAD])){
+ $request->set_write_stream($options[self::OSS_FILE_DOWNLOAD]);
+ }else{
+ $request->set_write_file($options[self::OSS_FILE_DOWNLOAD]);
+ }
+ }
+
+ if(isset($options[self::OSS_METHOD])){
+ $request->set_method($options[self::OSS_METHOD]);
+ $string_to_sign .= $options[self::OSS_METHOD] . "\n";
+ }
+
+ if (isset($options[self::OSS_CONTENT])) {
+ $request->set_body($options[self::OSS_CONTENT]);
+ if ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded'){
+ $headers[self::OSS_CONTENT_TYPE] = 'application/octet-stream';
+ }
+
+ $headers[self::OSS_CONTENT_LENGTH] = strlen($options[self::OSS_CONTENT]);
+ $headers[self::OSS_CONTENT_MD5] = base64_encode(md5($options[self::OSS_CONTENT], true));
+ }
+
+ uksort($headers, 'strnatcasecmp');
+
+ foreach($headers as $header_key => $header_value){
+ $header_value = str_replace(array ("\r", "\n"), '', $header_value);
+ if ($header_value !== '') {
+ $request->add_header($header_key, $header_value);
+ }
+
+ if (
+ strtolower($header_key) === 'content-md5' ||
+ strtolower($header_key) === 'content-type' ||
+ strtolower($header_key) === 'date' ||
+ (isset($options['self::OSS_PREAUTH']) && (integer) $options['self::OSS_PREAUTH'] > 0)
+ ){
+ $string_to_sign .= $header_value . "\n";
+ }elseif (substr(strtolower($header_key), 0, 6) === self::OSS_DEFAULT_PREFIX){
+ $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
+ }
+ }
+
+ $string_to_sign .= '/' . $options[self::OSS_BUCKET];
+ $string_to_sign .= $this->enable_domain_style ? ($options[self::OSS_BUCKET] != '' ? ($options[self::OSS_OBJECT]=='/'?'/':'') :''): '';
+ $string_to_sign .= rawurldecode($signable_resource) . urldecode($signable_query_string);
+
+ $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->access_key, true));
+ $request->add_header('Authorization', 'OSS ' . $this->access_id . ':' . $signature);
+
+ if (isset($options[self::OSS_PREAUTH]) && (integer) $options[self::OSS_PREAUTH] > 0){
+ $signed_url = $this->request_url . $conjunction . self::OSS_URL_ACCESS_KEY_ID.'=' . rawurlencode($this->access_id) . '&'.self::OSS_URL_EXPIRES.'=' . $options[self::OSS_PREAUTH] . '&'.self::OSS_URL_SIGNATURE.'=' . rawurlencode($signature);
+ return $signed_url;
+ }elseif (isset($options[self::OSS_PREAUTH])){
+ return $this->request_url;
+ }
+
+ if ($this->debug_mode){
+ $request->debug_mode = $this->debug_mode;
+ }
+
+ $request->send_request();
+
+ $response_header = $request->get_response_header();
+ $response_header['oss-request-url'] = $this->request_url;
+ $response_header['oss-redirects'] = $this->redirects;
+ $response_header['oss-stringtosign'] = $string_to_sign;
+ $response_header['oss-requestheaders'] = $request->request_headers;
+
+ $data = new ResponseCore($response_header , $request->get_response_body(), $request->get_response_code());
+
+ //retry if OSS Internal Error
+ if((integer)$request->get_response_code() === 500){
+ if($this->redirects <= $this->max_retries){
+ //设置休眠
+ $delay = (integer) (pow(4, $this->redirects) * 100000);
+ usleep($delay);
+ $this->redirects++;
+ $data = $this->auth($options);
+ }
+ }
+
+ $this->redirects = 0;
+ return $data;
+ }
+
+ /*%******************************************************************************************************%*/
+ //属性
+
+ /**
+ * 设置debug模式
+ * @param boolean $debug_mode (Optional)
+ * @author xiaobing
+ * @since 2012-05-29
+ * @return void
+ */
+ public function set_debug_mode($debug_mode = false){
+ $this->debug_mode = $debug_mode;
+ }
+ public function get_debug_mode(){
+ return $this->debug_mode;
+ }
+
+ /**
+ * 设置最大尝试次数
+ * @param int $max_retries
+ * @author xiaobing
+ * @since 2012-05-29
+ * @return void
+ */
+ public function set_max_retries($max_retries = 3){
+ $this->max_retries = $max_retries;
+ }
+
+ /**
+ * 获取最大尝试次数
+ * @author xiaobing
+ * @since 2012-05-29
+ * @return int
+ */
+ public function get_max_retries(){
+ return $this->max_retries;
+ }
+
+ /**
+ * 设置host地址
+ * @author xiaobing
+ * @param string $hostname host name
+ * @param int $port int
+ * @since 2012-06-11
+ * @return void
+ */
+ public function set_host_name($hostname, $port = null){
+ $this->hostname = $hostname;
+
+ if($port){
+ $this->port = $port;
+ $this->hostname .= ':'.$port;
+ }
+ }
+
+ public function get_host(){
+ return $this->hostname;
+ }
+
+ public function get_port(){
+ return $this->port;
+ }
+
+ public function get_id(){
+ return $this->access_id;
+ }
+
+ /**
+ * 设置vhost地址
+ * @author xiaobing
+ * @param string $vhost vhost
+ * @since 2012-06-11
+ * @return void
+ */
+ public function set_vhost($vhost){
+ $this->vhost = $vhost;
+ }
+
+ public function get_vhost(){
+ return $this->vhost;
+ }
+ /**
+ * 设置路径形式,如果为true,则启用三级域名,如bucket.oss.aliyuncs.com
+ * @author xiaobing
+ * @param boolean $enable_domain_style
+ * @since 2012-06-11
+ * @return void
+ */
+ public function set_enable_domain_style($enable_domain_style = true){
+ $this->enable_domain_style = $enable_domain_style;
+ }
+
+ public function get_enable_domain_style(){
+ return $this->enable_domain_style;
+ }
+
+ public function set_sign_sts_in_url($enable){
+ if ($enable) {
+ $this->enable_sts_in_url = true;
+ } else {
+ $this->enable_sts_in_url = false;
+ }
+ }
+
+ /*%******************************************************************************************************%*/
+ const DEFAULT_OSS_HOST = 'oss.aliyuncs.com';
+ const DEFAULT_OSS_ENDPOINT = 'oss.aliyuncs.com';
+ const NAME = OSS_NAME;
+ const BUILD = OSS_BUILD;
+ const VERSION = OSS_VERSION;
+ const AUTHOR = OSS_AUTHOR;
+ //OSS 内部常量
+ const OSS_BUCKET = 'bucket';
+ const OSS_OBJECT = 'object';
+ const OSS_HEADERS = OSSUtil::OSS_HEADERS;
+ const OSS_METHOD = 'method';
+ const OSS_QUERY = 'query';
+ const OSS_BASENAME = 'basename';
+ const OSS_MAX_KEYS = 'max-keys';
+ const OSS_UPLOAD_ID = 'uploadId';
+ const OSS_PART_NUM = 'partNumber';
+ const OSS_MAX_KEYS_VALUE = 100;
+ const OSS_MAX_OBJECT_GROUP_VALUE = OSSUtil::OSS_MAX_OBJECT_GROUP_VALUE;
+ const OSS_MAX_PART_SIZE = OSSUtil::OSS_MAX_PART_SIZE;
+ const OSS_MID_PART_SIZE = OSSUtil::OSS_MID_PART_SIZE;
+ const OSS_MIN_PART_SIZE = OSSUtil::OSS_MIN_PART_SIZE;
+ const OSS_FILE_SLICE_SIZE = 8192;
+ const OSS_PREFIX = 'prefix';
+ const OSS_DELIMITER = 'delimiter';
+ const OSS_MARKER = 'marker';
+ const OSS_CONTENT_MD5 = 'Content-Md5';
+ const OSS_SELF_CONTENT_MD5 = 'x-oss-meta-md5';
+ const OSS_CONTENT_TYPE = 'Content-Type';
+ const OSS_CONTENT_LENGTH = 'Content-Length';
+ const OSS_IF_MODIFIED_SINCE = 'If-Modified-Since';
+ const OSS_IF_UNMODIFIED_SINCE = 'If-Unmodified-Since';
+ const OSS_IF_MATCH = 'If-Match';
+ const OSS_IF_NONE_MATCH = 'If-None-Match';
+ const OSS_CACHE_CONTROL = 'Cache-Control';
+ const OSS_EXPIRES = 'Expires';
+ const OSS_PREAUTH = 'preauth';
+ const OSS_CONTENT_COING = 'Content-Coding';
+ const OSS_CONTENT_DISPOSTION = 'Content-Disposition';
+ const OSS_RANGE = 'range';
+ const OSS_ETAG = 'etag';
+ const OSS_LAST_MODIFIED = 'lastmodified';
+ const OS_CONTENT_RANGE = 'Content-Range';
+ const OSS_CONTENT = OSSUtil::OSS_CONTENT;
+ const OSS_BODY = 'body';
+ const OSS_LENGTH = OSSUtil::OSS_LENGTH;
+ const OSS_HOST = 'Host';
+ const OSS_DATE = 'Date';
+ const OSS_AUTHORIZATION = 'Authorization';
+ const OSS_FILE_DOWNLOAD = 'fileDownload';
+ const OSS_FILE_UPLOAD = 'fileUpload';
+ const OSS_PART_SIZE = 'partSize';
+ const OSS_SEEK_TO = 'seekTo';
+ const OSS_SIZE = 'size';
+ const OSS_QUERY_STRING = 'query_string';
+ const OSS_SUB_RESOURCE = 'sub_resource';
+ const OSS_DEFAULT_PREFIX = 'x-oss-';
+ const OSS_CHECK_MD5 = 'checkmd5';
+ /*%******************************************************************************************%*/
+ //私有URL变量
+ const OSS_URL_ACCESS_KEY_ID = 'OSSAccessKeyId';
+ const OSS_URL_EXPIRES = 'Expires';
+ const OSS_URL_SIGNATURE = 'Signature';
+ /*%******************************************************************************************%*/
+ //HTTP方法
+ const OSS_HTTP_GET = 'GET';
+ const OSS_HTTP_PUT = 'PUT';
+ const OSS_HTTP_HEAD = 'HEAD';
+ const OSS_HTTP_POST = 'POST';
+ const OSS_HTTP_DELETE = 'DELETE';
+ const OSS_HTTP_OPTIONS = 'OPTIONS';
+ /*%******************************************************************************************%*/
+ //其他常量
+ const OSS_ACL = 'x-oss-acl';
+ const OSS_OBJECT_GROUP = 'x-oss-file-group';
+ const OSS_MULTI_PART = 'uploads';
+ const OSS_MULTI_DELETE = 'delete';
+ const OSS_OBJECT_COPY_SOURCE = 'x-oss-copy-source';
+ const OSS_OBJECT_COPY_SOURCE_RANGE = "x-oss-copy-source-range";
+ //支持STS SecurityToken
+ const OSS_SECURITY_TOKEN = "x-oss-security-token";
+
+ const OSS_ACL_TYPE_PRIVATE = 'private';
+ const OSS_ACL_TYPE_PUBLIC_READ = 'public-read';
+ const OSS_ACL_TYPE_PUBLIC_READ_WRITE = 'public-read-write';
+ //OSS ACL数组
+ static $OSS_ACL_TYPES = array(
+ self::OSS_ACL_TYPE_PRIVATE,
+ self::OSS_ACL_TYPE_PUBLIC_READ,
+ self::OSS_ACL_TYPE_PUBLIC_READ_WRITE
+ );
+
+ //CORS 相关
+ const OSS_CORS_ALLOWED_ORIGIN='AllowedOrigin';
+ const OSS_CORS_ALLOWED_METHOD='AllowedMethod';
+ const OSS_CORS_ALLOWED_HEADER='AllowedHeader';
+ const OSS_CORS_EXPOSE_HEADER='ExposeHeader';
+ const OSS_CORS_MAX_AGE_SECONDS='MaxAgeSeconds';
+ const OSS_OPTIONS_ORIGIN = 'Origin';
+ const OSS_OPTIONS_REQUEST_METHOD = 'Access-Control-Request-Method';
+ const OSS_OPTIONS_REQUEST_HEADERS = 'Access-Control-Request-Headers';
+
+
+ /*%******************************************************************************************%*/
+ //是否使用SSL
+ public $version = OSS_VERSION;
+ protected $use_ssl = false;
+ //是否使用debug模式
+ private $debug_mode = false;
+ private $max_retries = 3;
+ private $redirects = 0;
+ private $vhost;
+ //路径表现方式
+ private $enable_domain_style = false;
+ private $request_url;
+ private $access_id;
+ private $access_key;
+ private $hostname;
+ private $port;
+ private $security_token;
+ private $enable_sts_in_url = false;
+}
diff --git a/AliOssSdk/thirdparty/xml2array.class.php b/AliOssSdk/thirdparty/xml2array.class.php
new file mode 100644
index 0000000..1e9f773
--- /dev/null
+++ b/AliOssSdk/thirdparty/xml2array.class.php
@@ -0,0 +1,139 @@
+formatOutput = $format_output;
+ self::$encoding = $encoding;
+ }
+
+ /**
+ * @param $input_xml
+ * @return mixed
+ * @throws Exception
+ */
+ public static function &createArray($input_xml) {
+ $xml = self::getXMLRoot();
+ if(is_string($input_xml)) {
+ $parsed = $xml->loadXML($input_xml);
+ if(!$parsed) {
+ throw new Exception('[XML2Array] Error parsing the XML string.');
+ }
+ } else {
+ if(get_class($input_xml) != 'DOMDocument') {
+ throw new Exception('[XML2Array] The input XML object should be of type: DOMDocument.');
+ }
+ $xml = self::$xml = $input_xml;
+ }
+ $array[$xml->documentElement->tagName] = self::convert($xml->documentElement);
+ self::$xml = null; // clear the xml node in the class for 2nd time use.
+ return $array;
+ }
+
+ /**
+ * Convert an Array to XML
+ * @param mixed $node - XML as a string or as an object of DOMDocument
+ * @return mixed
+ */
+ private static function &convert($node) {
+ $output = array();
+
+ switch ($node->nodeType) {
+ case XML_CDATA_SECTION_NODE:
+ $output['@cdata'] = trim($node->textContent);
+ break;
+
+ case XML_TEXT_NODE:
+ $output = trim($node->textContent);
+ break;
+
+ case XML_ELEMENT_NODE:
+
+ // for each child node, call the covert function recursively
+ for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) {
+ $child = $node->childNodes->item($i);
+ $v = self::convert($child);
+ if(isset($child->tagName)) {
+ $t = $child->tagName;
+
+ // assume more nodes of same kind are coming
+ if(!isset($output[$t])) {
+ $output[$t] = array();
+ }
+ $output[$t][] = $v;
+ } else {
+ //check if it is not an empty text node
+ if($v !== '') {
+ $output = $v;
+ }
+ }
+ }
+
+ if(is_array($output)) {
+ // if only one node of its kind, assign it directly instead if array($value);
+ foreach ($output as $t => $v) {
+ if(is_array($v) && count($v)==1) {
+ $output[$t] = $v[0];
+ }
+ }
+ if(empty($output)) {
+ //for empty nodes
+ $output = '';
+ }
+ }
+
+ // loop through the attributes and collect them
+ if($node->attributes->length) {
+ $a = array();
+ foreach($node->attributes as $attrName => $attrNode) {
+ $a[$attrName] = (string) $attrNode->value;
+ }
+ // if its an leaf node, store the value in @value instead of directly storing it.
+ if(!is_array($output)) {
+ $output = array('@value' => $output);
+ }
+ $output['@attributes'] = $a;
+ }
+ break;
+ }
+ return $output;
+ }
+
+ /*
+ * Get the root XML node, if there isn't one, create it.
+ */
+ private static function getXMLRoot(){
+ if(empty(self::$xml)) {
+ self::init();
+ }
+ return self::$xml;
+ }
+}
diff --git a/AliOssSdk/util/mimetypes.class.php b/AliOssSdk/util/mimetypes.class.php
new file mode 100644
index 0000000..f90a6e2
--- /dev/null
+++ b/AliOssSdk/util/mimetypes.class.php
@@ -0,0 +1,240 @@
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
+ 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
+ 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
+ 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
+ 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
+ 'apk' => 'application/vnd.android.package-archive',
+
+ 'hqx' => 'application/mac-binhex40',
+ 'cpt' => 'application/mac-compactpro',
+ 'doc' => 'application/msword',
+ 'ogg' => 'application/ogg',
+ 'pdf' => 'application/pdf',
+ 'rtf' => 'text/rtf',
+ 'mif' => 'application/vnd.mif',
+ 'xls' => 'application/vnd.ms-excel',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'odc' => 'application/vnd.oasis.opendocument.chart',
+ 'odb' => 'application/vnd.oasis.opendocument.database',
+ 'odf' => 'application/vnd.oasis.opendocument.formula',
+ 'odg' => 'application/vnd.oasis.opendocument.graphics',
+ 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
+ 'odi' => 'application/vnd.oasis.opendocument.image',
+ 'odp' => 'application/vnd.oasis.opendocument.presentation',
+ 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
+ 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
+ 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
+ 'odt' => 'application/vnd.oasis.opendocument.text',
+ 'odm' => 'application/vnd.oasis.opendocument.text-master',
+ 'ott' => 'application/vnd.oasis.opendocument.text-template',
+ 'oth' => 'application/vnd.oasis.opendocument.text-web',
+ 'sxw' => 'application/vnd.sun.xml.writer',
+ 'stw' => 'application/vnd.sun.xml.writer.template',
+ 'sxc' => 'application/vnd.sun.xml.calc',
+ 'stc' => 'application/vnd.sun.xml.calc.template',
+ 'sxd' => 'application/vnd.sun.xml.draw',
+ 'std' => 'application/vnd.sun.xml.draw.template',
+ 'sxi' => 'application/vnd.sun.xml.impress',
+ 'sti' => 'application/vnd.sun.xml.impress.template',
+ 'sxg' => 'application/vnd.sun.xml.writer.global',
+ 'sxm' => 'application/vnd.sun.xml.math',
+ 'sis' => 'application/vnd.symbian.install',
+ 'wbxml' => 'application/vnd.wap.wbxml',
+ 'wmlc' => 'application/vnd.wap.wmlc',
+ 'wmlsc' => 'application/vnd.wap.wmlscriptc',
+ 'bcpio' => 'application/x-bcpio',
+ 'torrent' => 'application/x-bittorrent',
+ 'bz2' => 'application/x-bzip2',
+ 'vcd' => 'application/x-cdlink',
+ 'pgn' => 'application/x-chess-pgn',
+ 'cpio' => 'application/x-cpio',
+ 'csh' => 'application/x-csh',
+ 'dvi' => 'application/x-dvi',
+ 'spl' => 'application/x-futuresplash',
+ 'gtar' => 'application/x-gtar',
+ 'hdf' => 'application/x-hdf',
+ 'jar' => 'application/x-java-archive',
+ 'jnlp' => 'application/x-java-jnlp-file',
+ 'js' => 'application/x-javascript',
+ 'ksp' => 'application/x-kspread',
+ 'chrt' => 'application/x-kchart',
+ 'kil' => 'application/x-killustrator',
+ 'latex' => 'application/x-latex',
+ 'rpm' => 'application/x-rpm',
+ 'sh' => 'application/x-sh',
+ 'shar' => 'application/x-shar',
+ 'swf' => 'application/x-shockwave-flash',
+ 'sit' => 'application/x-stuffit',
+ 'sv4cpio' => 'application/x-sv4cpio',
+ 'sv4crc' => 'application/x-sv4crc',
+ 'tar' => 'application/x-tar',
+ 'tcl' => 'application/x-tcl',
+ 'tex' => 'application/x-tex',
+ 'man' => 'application/x-troff-man',
+ 'me' => 'application/x-troff-me',
+ 'ms' => 'application/x-troff-ms',
+ 'ustar' => 'application/x-ustar',
+ 'src' => 'application/x-wais-source',
+ 'zip' => 'application/zip',
+ 'm3u' => 'audio/x-mpegurl',
+ 'ra' => 'audio/x-pn-realaudio',
+ 'wav' => 'audio/x-wav',
+ 'wma' => 'audio/x-ms-wma',
+ 'wax' => 'audio/x-ms-wax',
+ 'pdb' => 'chemical/x-pdb',
+ 'xyz' => 'chemical/x-xyz',
+ 'bmp' => 'image/bmp',
+ 'gif' => 'image/gif',
+ 'ief' => 'image/ief',
+ 'png' => 'image/png',
+ 'wbmp' => 'image/vnd.wap.wbmp',
+ 'ras' => 'image/x-cmu-raster',
+ 'pnm' => 'image/x-portable-anymap',
+ 'pbm' => 'image/x-portable-bitmap',
+ 'pgm' => 'image/x-portable-graymap',
+ 'ppm' => 'image/x-portable-pixmap',
+ 'rgb' => 'image/x-rgb',
+ 'xbm' => 'image/x-xbitmap',
+ 'xpm' => 'image/x-xpixmap',
+ 'xwd' => 'image/x-xwindowdump',
+ 'css' => 'text/css',
+ 'rtx' => 'text/richtext',
+ 'tsv' => 'text/tab-separated-values',
+ 'jad' => 'text/vnd.sun.j2me.app-descriptor',
+ 'wml' => 'text/vnd.wap.wml',
+ 'wmls' => 'text/vnd.wap.wmlscript',
+ 'etx' => 'text/x-setext',
+ 'mxu' => 'video/vnd.mpegurl',
+ 'flv' => 'video/x-flv',
+ 'wm' => 'video/x-ms-wm',
+ 'wmv' => 'video/x-ms-wmv',
+ 'wmx' => 'video/x-ms-wmx',
+ 'wvx' => 'video/x-ms-wvx',
+ 'avi' => 'video/x-msvideo',
+ 'movie' => 'video/x-sgi-movie',
+ 'ice' => 'x-conference/x-cooltalk',
+ '3gp' => 'video/3gpp',
+ 'ai' => 'application/postscript',
+ 'aif' => 'audio/x-aiff',
+ 'aifc' => 'audio/x-aiff',
+ 'aiff' => 'audio/x-aiff',
+ 'asc' => 'text/plain',
+ 'atom' => 'application/atom+xml',
+ 'au' => 'audio/basic',
+ 'bin' => 'application/octet-stream',
+ 'cdf' => 'application/x-netcdf',
+ 'cgm' => 'image/cgm',
+ 'class' => 'application/octet-stream',
+ 'dcr' => 'application/x-director',
+ 'dif' => 'video/x-dv',
+ 'dir' => 'application/x-director',
+ 'djv' => 'image/vnd.djvu',
+ 'djvu' => 'image/vnd.djvu',
+ 'dll' => 'application/octet-stream',
+ 'dmg' => 'application/octet-stream',
+ 'dms' => 'application/octet-stream',
+ 'dtd' => 'application/xml-dtd',
+ 'dv' => 'video/x-dv',
+ 'dxr' => 'application/x-director',
+ 'eps' => 'application/postscript',
+ 'exe' => 'application/octet-stream',
+ 'ez' => 'application/andrew-inset',
+ 'gram' => 'application/srgs',
+ 'grxml' => 'application/srgs+xml',
+ 'gz' => 'application/x-gzip',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'ico' => 'image/x-icon',
+ 'ics' => 'text/calendar',
+ 'ifb' => 'text/calendar',
+ 'iges' => 'model/iges',
+ 'igs' => 'model/iges',
+ 'jp2' => 'image/jp2',
+ 'jpe' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'kar' => 'audio/midi',
+ 'lha' => 'application/octet-stream',
+ 'lzh' => 'application/octet-stream',
+ 'm4a' => 'audio/mp4a-latm',
+ 'm4p' => 'audio/mp4a-latm',
+ 'm4u' => 'video/vnd.mpegurl',
+ 'm4v' => 'video/x-m4v',
+ 'mac' => 'image/x-macpaint',
+ 'mathml' => 'application/mathml+xml',
+ 'mesh' => 'model/mesh',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'mov' => 'video/quicktime',
+ 'mp2' => 'audio/mpeg',
+ 'mp3' => 'audio/mpeg',
+ 'mp4' => 'video/mp4',
+ 'mpe' => 'video/mpeg',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mpga' => 'audio/mpeg',
+ 'msh' => 'model/mesh',
+ 'nc' => 'application/x-netcdf',
+ 'oda' => 'application/oda',
+ 'ogv' => 'video/ogv',
+ 'pct' => 'image/pict',
+ 'pic' => 'image/pict',
+ 'pict' => 'image/pict',
+ 'pnt' => 'image/x-macpaint',
+ 'pntg' => 'image/x-macpaint',
+ 'ps' => 'application/postscript',
+ 'qt' => 'video/quicktime',
+ 'qti' => 'image/x-quicktime',
+ 'qtif' => 'image/x-quicktime',
+ 'ram' => 'audio/x-pn-realaudio',
+ 'rdf' => 'application/rdf+xml',
+ 'rm' => 'application/vnd.rn-realmedia',
+ 'roff' => 'application/x-troff',
+ 'sgm' => 'text/sgml',
+ 'sgml' => 'text/sgml',
+ 'silo' => 'model/mesh',
+ 'skd' => 'application/x-koan',
+ 'skm' => 'application/x-koan',
+ 'skp' => 'application/x-koan',
+ 'skt' => 'application/x-koan',
+ 'smi' => 'application/smil',
+ 'smil' => 'application/smil',
+ 'snd' => 'audio/basic',
+ 'so' => 'application/octet-stream',
+ 'svg' => 'image/svg+xml',
+ 't' => 'application/x-troff',
+ 'texi' => 'application/x-texinfo',
+ 'texinfo' => 'application/x-texinfo',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'tr' => 'application/x-troff',
+ 'txt' => 'text/plain',
+ 'vrml' => 'model/vrml',
+ 'vxml' => 'application/voicexml+xml',
+ 'webm' => 'video/webm',
+ 'wrl' => 'model/vrml',
+ 'xht' => 'application/xhtml+xml',
+ 'xhtml' => 'application/xhtml+xml',
+ 'xml' => 'application/xml',
+ 'xsl' => 'application/xml',
+ 'xslt' => 'application/xslt+xml',
+ 'xul' => 'application/vnd.mozilla.xul+xml',
+ );
+
+ public static function get_mimetype($ext) {
+ return (isset ( self::$mime_types [$ext] ) ? self::$mime_types [$ext] : 'application/octet-stream');
+ }
+}
diff --git a/AliOssSdk/util/oss_util.class.php b/AliOssSdk/util/oss_util.class.php
new file mode 100644
index 0000000..a6b9d82
--- /dev/null
+++ b/AliOssSdk/util/oss_util.class.php
@@ -0,0 +1,434 @@
+IsTruncated;
+ $object_list = array();
+ $marker = $xml->NextMarker;
+ foreach ( $xml->Contents as $content) {
+ array_push($object_list, $content->Key);
+ }
+ return $object_list;
+ }
+
+ public static function print_res($response, $msg = "", $is_simple_print = true){
+ if ($is_simple_print){
+ if ((int)($response->status / 100) == 2){
+ echo $msg." OK\n";
+ }
+ else{
+ echo "ret:".$response->status."\n";
+ echo $msg." FAIL\n";
+ }
+ }
+ else {
+ echo '|-----------------------Start---------------------------------------------------------------------------------------------------'."\n";
+ echo '|-Status:' . $response->status . "\n";
+ echo '|-Body:' ."\n";
+ $body = $response->body . "\n";
+ echo $body . "\n";
+ echo "|-Header:\n";
+ print_r ($response->header);
+ echo '-----------------------End-----------------------------------------------------------------------------------------------------'."\n\n";
+ }
+ }
+
+ /*%******************************************************************************************************%*/
+ //工具类相关
+
+ /**
+ * 生成query params
+ * @param array $array 关联数组
+ * @return string 返回诸如 key1=value1&key2=value2
+ */
+ public static function to_query_string($options = array()){
+ $temp = array();
+ uksort($options, 'strnatcasecmp');
+ foreach ($options as $key => $value){
+ if (is_string($key) && !is_array($value)){
+ $temp[] = rawurlencode($key) . '=' . rawurlencode($value);
+ }
+ }
+ return implode('&', $temp);
+ }
+
+ /**
+ * @param $str
+ * @return string
+ */
+ public static function hex_to_base64($str){
+ $result = '';
+ for ($i = 0; $i < strlen($str); $i += 2){
+ $result .= chr(hexdec(substr($str, $i, 2)));
+ }
+ return base64_encode($result);
+ }
+
+ public static function s_replace($subject){
+ $search = array('<', '>', '&', '\'', '"');
+ $replace = array('<', '>', '&', ''', '"');
+ return str_replace($search, $replace, $subject);
+ }
+
+ /**
+ * @param $subject
+ * @return mixed
+ */
+ public static function replace_invalid_xml_char($subject){
+ $search = array(
+ '', '', '', '', '', '', '', '', ' ', '
', '', '', '
',
+ '', '', '', '', '', '', '', '', '', '', '', '', '',
+ '', '', '', '', '', ''
+ );
+ $replace = array(
+ '%01', '%02', '%03', '%04', '%05', '%06', '%07', '%08', '%09', '%0A', '%0B', '%0C', '%0D',
+ '%0E', '%0F', '%10', '%11', '%12', '%13', '%14', '%15', '%16', '%17', '%18', '%19', '%1A',
+ '%1B', '%1C', '%1D', '%1E', '%1F', '%7F'
+ );
+
+ return str_replace($search, $replace, $subject);
+ }
+
+ /**
+ * @param $str
+ * @return int
+ */
+ public static function chk_chinese($str){
+ return preg_match('/[\x80-\xff]./', $str);
+ }
+
+ /**
+ * 检测是否GB2312编码
+ * @param string $str
+ * @author xiaobing
+ * @since 2012-03-20
+ * @return boolean false UTF-8编码 TRUE GB2312编码
+ */
+ public static function is_gb2312($str) {
+ for($i=0; $i 127) {
+ if( ($v >= 228) && ($v <= 233)){
+ if( ($i+2) >= (strlen($str) - 1)) return true; // not enough characters
+ $v1 = ord( $str[$i+1]);
+ $v2 = ord( $str[$i+2]);
+ if( ($v1 >= 128) && ($v1 <=191) && ($v2 >=128) && ($v2 <= 191))
+ return false; //UTF-8编码
+ else
+ return true; //GB编码
+ }
+ }
+ }
+ }
+
+ /**
+ * 检测是否GBK编码
+ * @param string $str
+ * @param boolean $gbk
+ * @author xiaobing
+ * @since 2012-06-04
+ * @return boolean
+ */
+ public static function check_char($str, $gbk = true){
+ for($i=0; $i 127){
+ if( ($v >= 228) && ($v <= 233)){
+ if(($i+2)>= (strlen($str)-1)) return $gbk?true:FALSE; // not enough characters
+ $v1 = ord( $str[$i+1]); $v2 = ord( $str[$i+2]);
+ if($gbk){
+ return (($v1 >= 128) && ($v1 <=191) && ($v2 >=128) && ($v2 <= 191))?FALSE:TRUE;//GBK
+ }else{
+ return (($v1 >= 128) && ($v1 <=191) && ($v2 >=128) && ($v2 <= 191))?TRUE:FALSE;
+ }
+ }
+ }
+ }
+ return $gbk?TRUE:FALSE;
+ }
+
+
+ /**
+ * 检验bucket名称是否合法
+ * bucket的命名规范:
+ * 1. 只能包括小写字母,数字
+ * 2. 必须以小写字母或者数字开头
+ * 3. 长度必须在3-63字节之间
+ * @param string $bucket (Required)
+ * @author xiaobing
+ * @since 2011-12-27
+ * @return boolean
+ */
+ public static function validate_bucket($bucket){
+ $pattern = '/^[a-z0-9][a-z0-9-]{2,62}$/';
+ if (!preg_match($pattern, $bucket)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 检验object名称是否合法
+ * object命名规范:
+ * 1. 规则长度必须在1-1023字节之间
+ * 2. 使用UTF-8编码
+ * @param string $object (Required)
+ * @author xiaobing
+ * @since 2011-12-27
+ * @return boolean
+ */
+ public static function validate_object($object){
+ $pattern = '/^.{1,1023}$/';
+ if (empty($object) || !preg_match($pattern, $object)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 检验$options
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author xiaobing
+ * @since 2011-12-27
+ * @return boolean
+ */
+ public static function validate_options($options){
+ //$options
+ if ($options != NULL && !is_array($options)) {
+ throw new OSS_Exception ($options.':'.OSS_OPTIONS_MUST_BE_ARRAY);
+ }
+ }
+
+ /**
+ * 检测上传文件的内容
+ * @param array $options (Optional)
+ * @throws OSS_Exception
+ * @author xiaobing
+ * @since 2011-12-27
+ * @return string
+ */
+ public static function validate_content($options){
+ if(isset($options[self::OSS_CONTENT])){
+ if($options[self::OSS_CONTENT] == '' || !is_string($options[self::OSS_CONTENT])){
+ throw new OSS_Exception(OSS_INVALID_HTTP_BODY_CONTENT,'-600');
+ }
+ }else{
+ throw new OSS_Exception(OSS_NOT_SET_HTTP_CONTENT, '-601');
+ }
+ }
+
+ /**
+ * @param $options
+ * @throws OSS_Exception
+ */
+ public static function validate_content_length($options){
+ if(isset($options[self::OSS_LENGTH]) && is_numeric($options[self::OSS_LENGTH])){
+ if( !$options[self::OSS_LENGTH] > 0){
+ throw new OSS_Exception(OSS_CONTENT_LENGTH_MUST_MORE_THAN_ZERO, '-602');
+ }
+ }else{
+ throw new OSS_Exception(OSS_INVALID_CONTENT_LENGTH, '-602');
+ }
+ }
+
+ /**
+ * 校验BUCKET/OBJECT/OBJECT GROUP是否为空
+ * @param string $name (Required)
+ * @param string $errMsg (Required)
+ * @throws OSS_Exception
+ * @author xiaobing
+ * @since 2011-12-27
+ * @return void
+ */
+ public static function is_empty($name,$errMsg){
+ if(empty($name)){
+ throw new OSS_Exception($errMsg);
+ }
+ }
+
+ /**
+ * 设置http header
+ * @param string $key (Required)
+ * @param string $value (Required)
+ * @param array $options (Required)
+ * @throws OSS_Exception
+ * @author xiaobing
+ * @return void
+ */
+ public static function set_options_header($key, $value, &$options) {
+ if (isset($options[self::OSS_HEADERS])) {
+ if (!is_array($options[self::OSS_HEADERS])) {
+ throw new OSS_Exception(OSS_INVALID_OPTION_HEADERS, '-600');
+ }
+ } else {
+ $options[self::OSS_HEADERS] = array ();
+ }
+ $options[self::OSS_HEADERS][$key] = $value;
+ }
+
+ /**
+ * 仅供测试使用的接口,请勿使用
+ */
+ public static function generate_file($filename, $size) {
+ if (file_exists($filename) && $size == filesize($filename)) {
+ echo $filename." already exists, no need to create again. ";
+ return;
+ }
+ $part_size = 1*1024*1024;
+ $write_size = 0;
+ $fp = fopen($filename, "w");
+ $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ $charactersLength = strlen($characters);
+ if($fp)
+ {
+ while ($size > 0) {
+ if ($size < $part_size) {
+ $write_size = $size;
+ } else {
+ $write_size = $part_size;
+ }
+ $size -= $write_size;
+ $a = $characters[rand(0, $charactersLength - 1)];
+ $content = str_repeat($a, $write_size);
+ $flag = fwrite($fp, $content);
+ if(!$flag)
+ {
+ echo "write to ". $filename . " failed. ";
+ break;
+ }
+ }
+ }
+ else
+ {
+ echo "open ". $filename . " failed. ";
+ }
+ fclose($fp);
+ }
+
+ public static function get_content_md5_of_file($filename, $from_pos, $to_pos) {
+ $content_md5 = "";
+ if (($to_pos - $from_pos) > self::OSS_MAX_PART_SIZE) {
+ return $content_md5;
+ }
+ $filesize = filesize($filename);
+ if ($from_pos >= $filesize || $to_pos >= $filesize || $from_pos < 0 || $to_pos < 0) {
+ return $content_md5;
+ }
+
+ $total_length = $to_pos - $from_pos + 1;
+ $buffer = 8192;
+ $left_length = $total_length;
+ if (!file_exists($filename)) {
+ return $content_md5;
+ }
+
+ if (false === $fh = fopen($filename, 'rb')) {
+ return $content_md5;
+ }
+
+ fseek($fh, $from_pos);
+ $data = '';
+ while (!feof($fh)) {
+ if ($left_length >= $buffer) {
+ $read_length = $buffer;
+ }
+ else {
+ $read_length = $left_length;
+ }
+ if ($read_length <= 0) {
+ break;
+ }
+ else {
+ $data .= fread($fh, $read_length);
+ $left_length = $left_length - $read_length;
+ }
+ }
+ fclose($fh);
+ $content_md5 = base64_encode(md5($data, true));
+ return $content_md5;
+ }
+
+ /**
+ * 检测是否windows系统,因为windows系统默认编码为GBK
+ * @return bool
+ */
+ public static function is_win(){
+ return strtoupper(substr(PHP_OS,0,3)) == "WIN";
+ }
+
+ /**
+ * 主要是由于windows系统编码是gbk,遇到中文时候,如果不进行转换处理会出现找不到文件的问题
+ * @param $file_path
+ * @return string
+ */
+ public static function encoding_path($file_path){
+ if(self::chk_chinese($file_path) && self::is_win()){
+ $file_path = iconv('utf-8', 'gbk',$file_path);
+ }
+ return $file_path;
+ }
+
+ /**
+ * 转换响应
+ * @param $response
+ * @return array
+ * @throws Exception
+ */
+ public static function parse_response($response, $format="array"){
+ //如果启用响应结果转换,则进行转换,否则原样返回
+ $body = $response->body;
+ $headers = $response->header;
+
+ switch (strtolower($format)) {
+ case 'array':
+ $body = empty($body) ? $body : XML2Array::createArray($body);
+ break;
+ case "json":
+ $body = empty($body) ? $body : json_encode(XML2Array::createArray($body));
+ break;
+ default:
+ break;
+ }
+
+ return array(
+ 'success' => $response->isOk(),
+ 'status' => $response->status,
+ 'header' => $headers,
+ 'body' => $body
+ );
+ return $response;
+ }
+}
diff --git a/Plugin.php b/Plugin.php
new file mode 100644
index 0000000..08b7254
--- /dev/null
+++ b/Plugin.php
@@ -0,0 +1,586 @@
+uploadHandle = array('AliOssForTypecho_Plugin', 'uploadHandle');
+ Typecho_Plugin::factory('Widget_Upload')->modifyHandle = array('AliOssForTypecho_Plugin', 'modifyHandle');
+ Typecho_Plugin::factory('Widget_Upload')->deleteHandle = array('AliOssForTypecho_Plugin', 'deleteHandle');
+ Typecho_Plugin::factory('Widget_Upload')->attachmentHandle = array('AliOssForTypecho_Plugin', 'attachmentHandle');
+ Typecho_Plugin::factory('Widget_Upload')->attachmentDataHandle = array('AliOssForTypecho_Plugin', 'attachmentDataHandle');
+
+ return _t('启用成功,请进行相应设置!');
+ }
+
+ /**
+ * 禁用插件方法,如果禁用失败,直接抛出异常
+ *
+ * @static
+ * @access public
+ * @return void
+ * @throws Typecho_Plugin_Exception
+ */
+ public static function deactivate(){}
+
+ /**
+ * 获取插件配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form 配置面板
+ * @return void
+ */
+ public static function config(Typecho_Widget_Helper_Form $form)
+ { $des = new Typecho_Widget_Helper_Form_Element_Text('des', NULL, '', _t('插件使用说明;'),
+ _t('
+ - 插件基于阿里云oss_php_sdk_20150819开发包开发,若以后SDK开发包更新导致插件不可用,请到 我的博客 ^ - ^获取新版本插件,如果我还用typecho还用阿里云就会更新。
+ - 阿里云OSS支持自定义域名到OSS获取文件,如果你的站点运行在阿里云ECS或ACE并十分清楚阿里云服务的内网互通规则,配置连接Bucket与获取文件使用不同的链接可以节省流量。如果你不清楚这些,那么就选择Bucket所在节点的外网地址。
+ - 运行在云应用引擎上的站点可以使用本插件,插件不会保存文件到服务器,“在服务器保留备份”选项无效。
+ - 若开启“在服务器保留备份”功能:
插件尽在上传到OSS失败或者遇到其他错误时会返回错误信息,成功保存到OSS但是没有成功保存到服务器的情况下,插件不会抛出异常,上传过程会继续进行,但是会在' . __TYPECHO_ROOT_DIR__ . self::log_path . '目录下生成错误日志"error.log",请定期查阅并清理。
+ - 未作容错性检测,配置错误会导致上传失败。
+ - Typecho原因无法上传大写扩展名文件,本插件不做修补,等待Typecho更新。
+ - 如有问题请到 我的博客 留言
+ '));
+ $form->addInput($des);
+
+ $buketName = new Typecho_Widget_Helper_Form_Element_Text('bucketName', NULL, 'yourself bucketName',
+ _t('Bucket名称'), _t('请填写Buket名称'));
+ $form->addInput($buketName->addRule('required', _t('必须填写Bucket名称')));
+
+ $accessId = new Typecho_Widget_Helper_Form_Element_Text('accessId', NULL, 'yourself AccessId',
+ _t('ACCESS_ID'), _t('请填写ACCESS_ID'));
+ $form->addInput($accessId->addRule('required', _t('必须填写ACCESS_ID')));
+
+ $accessKey = new Typecho_Widget_Helper_Form_Element_Text('accessKey', NULL, 'yourself AccessKey',
+ _t('ACCESS_KEY'), _t('请填写请填写ACCESS_KEY'));
+ $form->addInput($accessKey->addRule('required', _t('必须填写ACCESS_KEY')));
+
+ $endPoint = new Typecho_Widget_Helper_Form_Element_Select('endPoint',
+ array(
+ "oss-cn-qingdao.aliyuncs.com" => '青岛节点外网地址: oss-cn-qingdao.aliyuncs.com',
+ "oss-cn-qingdao-internal.aliyuncs.com" => '青岛节点内网地址: oss-cn-qingdao-internal.aliyuncs.com',
+ "oss-cn-beijing.aliyuncs.com" => '北京节点外网地址: oss-cn-beijing.aliyuncs.com',
+ "oss-cn-beijing-internal.aliyuncs.com" => '北京节点内网地址: oss-cn-beijing-internal.aliyuncs.com',
+ "oss-cn-hangzhou.aliyuncs.com" => '杭州节点外网地址: oss-cn-hangzhou.aliyuncs.com',
+ "oss-cn-hangzhou-internal.aliyuncs.com" => '杭州节点内网地址: oss-cn-hangzhou-internal.aliyuncs.com',
+ "oss-cn-hongkong.aliyuncs.com" => '香港节点外网地址: oss-cn-hongkong.aliyuncs.com',
+ "oss-cn-hongkong-internal.aliyuncs.com" => '香港节点内网地址: oss-cn-hongkong-internal.aliyuncs.com',
+ "oss-cn-shenzhen.aliyuncs.com" => '深圳节点外网地址: oss-cn-shenzhen.aliyuncs.com',
+ "oss-cn-shenzhen-internal.aliyuncs.com" => '深圳节点内网地址: oss-cn-shenzhen-internal.aliyuncs.com',
+ "oss-cn-shanghai.aliyuncs.com" => '上海节点外网地址: oss-cn-shanghai.aliyuncs.com',
+ "oss-cn-shanghai-internal.aliyuncs.com" => '上海节点内网地址: oss-cn-shanghai-internal.aliyuncs.com',
+ "oss-us-west-1.aliyuncs.com" => '美国硅谷节点外网地址: oss-us-west-1.aliyuncs.com',
+ "oss-us-west-1-internal.aliyuncs.com" => '美国硅谷节点内网地址: oss-us-west-1-internal.aliyuncs.com',
+ "oss-ap-southeast-1.aliyuncs.com" => '亚太(新加坡)节点外网地址: oss-ap-southeast-1.aliyuncs.com',
+ "oss-ap-southeast-1-internal.aliyuncs.com" => '亚太(新加坡)节点内网地址: oss-ap-southeast-1-internal.aliyuncs.com',
+ "other" => '其他'
+ ),
+ 'oss-cn-qingdao.aliyuncs.com', _t('连接Bucket结点所用地址'), _t('参见使用说明第二条'));
+ $form->addInput($endPoint);
+
+ $otherEndPoint = new Typecho_Widget_Helper_Form_Element_Text('otherEndPoint', NULL, '填写其他节点',
+ '', _t('不包含http://,结尾不包含"/"'));
+ $form->addInput($otherEndPoint);
+
+ $userDir = new Typecho_Widget_Helper_Form_Element_Text('userDir', NULL, 'typecho/',
+ _t('要储存的路径'), _t('请填写文件储存的路径(相对OSS根目录),以字母或数字开头,以"/"结尾。留空则上传到根目录。'));
+ $form->addInput($userDir);
+
+ $cdnUrl = new Typecho_Widget_Helper_Form_Element_Text('cdnUrl', NULL, '',
+ _t('自定义域名'), _t('请填写自定义域名,留空则访问OSS源,不包含http://,结尾不包含"/"'));
+ $form->addInput($cdnUrl);
+
+ $ifLoaclSave = new Typecho_Widget_Helper_Form_Element_Radio('ifLoaclSave', array( "1" => '保留', "0" => '不保留' ), "1",
+ _t('在服务器保留备份'), _t('是否在服务器保留备份'));
+ $form->addInput($ifLoaclSave);
+
+ echo '';
+ }
+
+ /**
+ * 个人用户的配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form
+ * @return void
+ */
+ public static function personalConfig(Typecho_Widget_Helper_Form $form){}
+
+ /**
+ * 上传文件处理函数
+ *
+ * @access public
+ * @param array $file 上传的文件
+ * @return mixed
+ */
+ public static function uploadHandle($file)
+ {
+ if (empty($file['name']))
+ {
+ return FALSE;
+ }
+
+ $ext = self::getSafeName($file['name']);
+
+ if (!self::checkFileType($ext))
+ {
+ return FALSE;
+ }
+
+ $options = Typecho_Widget::widget('Widget_Options');
+ $date = new Typecho_Date($options->gmtTime);
+ $path = $date->year . '/' . $date->month. '/' . $date->day . '/';
+
+ //获取文件名
+ $fileName = substr(time(), 5) . sprintf('%u', crc32(uniqid())) . '.' . $ext;
+
+ $userDir = $options->plugin('AliOssForTypecho')->userDir;
+ $bucket_name = $options->plugin('AliOssForTypecho')->bucketName;
+ $end_point = ($options->plugin('AliOssForTypecho')->endPoint === "other") ?
+ $options->plugin('AliOssForTypecho')->otherEndPoint :
+ $options->plugin('AliOssForTypecho')->endPoint;
+ $access_id = $options->plugin('AliOssForTypecho')->accessId;
+ $access_key = $options->plugin('AliOssForTypecho')->accessKey;
+
+ $localFile = $path . $fileName;
+ $object_name = $userDir . $localFile;
+
+ if (isset($file['tmp_name']))
+ {
+ $content = file_get_contents($file['tmp_name']);
+ } else if (isset($file['bytes']))
+ {
+ $content = $file['bytes'];
+ } else
+ {
+ return FALSE;
+ }
+
+ $fileSize = strlen($content);
+ $ali_options = array(
+ 'content' => $content,
+ 'length' => $fileSize,
+ ALIOSS::OSS_HEADERS => array(
+ 'Content-Encoding' => 'utf-8',
+ 'Content-Language' => 'zh-CN',
+ ),
+ );
+
+ $client = new ALIOSS($access_id, $access_key, $end_point);
+ $client->set_enable_domain_style(TRUE);
+
+ $ali_response = $client->upload_file_by_content($bucket_name, $object_name, $ali_options);
+
+ if (200 != $ali_response->status)
+ {
+ return FALSE;
+ } else
+ {
+ $object_url = $ali_response->header["_info"]["url"];
+
+ $ifLoaclSave = $options->plugin('AliOssForTypecho')->ifLoaclSave;
+
+ if ($ifLoaclSave === "1" && !Typecho_Common::isAppEngine())
+ {
+
+ $localPath = Typecho_Common::url(defined('__TYPECHO_UPLOAD_DIR__') ? __TYPECHO_UPLOAD_DIR__ : self::UPLOAD_DIR,
+ defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__)
+ . '/' . $path;
+ $mkdirSuccess = TRUE;
+ //创建上传目录
+ if (!is_dir($localPath))
+ {
+ if (!self::makeUploadDir($localPath))
+ {
+ $mkdirSuccess = FALSE;
+ }
+ }
+
+ $saveOnServerSuccess = FALSE;
+
+ //保存文件到服务器
+
+ if ($mkdirSuccess)
+ {
+ if (file_put_contents($localPath.$fileName, $content))
+ {
+ $saveOnServerSuccess = TRUE;
+ } else
+ {
+ $error = '错误:保存文件失败' . "\r\n" .
+ '远程文件:' . $object_url . "\r\n" .
+ '时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
+ error_log($error, 3, $error_log_path . "error.log");
+ }
+ } else
+ {
+ $error = '错误:创建目录失败' . "\r\n" .
+ '创建路径:' . $localPath . "\r\n" .
+ '远程文件:' . $object_url . "\r\n" .
+ '时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
+ error_log($error, 3, $error_log_path . "error.log");
+ }
+ }
+ }
+
+ $name = $file['name'];
+ //返回相对存储路径
+ return array(
+ 'name' => $name,
+ 'path' => $localFile,
+ 'size' => $fileSize,
+ 'type' => $ext,
+ 'mime' => Typecho_Common::mimeContentType($localPath . $fileName)
+ );
+ }
+
+ /**
+ * 修改文件处理函数
+ *
+ * @access public
+ * @param array $content 老文件
+ * @param array $file 新上传的文件
+ * @return mixed
+ */
+ public static function modifyHandle($content, $file)
+ {
+ if (empty($file['name'])) {
+ return false;
+ }
+
+ $ext = self::getSafeName($file['name']);
+
+ if ($content['attachment']->type != $ext) {
+ return false;
+ }
+
+ if (isset($file['tmp_name'])) {
+ $newContent = file_get_contents($file['tmp_name']);
+ } else if (isset($file['bytes'])) {
+ $newContent = $file['bytes'];
+ } else {
+ return false;
+ }
+
+ $options = Typecho_Widget::widget('Widget_Options');
+ $date = new Typecho_Date($options->gmtTime);
+
+ $path = $content['attachment']->path;
+
+ $userDir = $options->plugin('AliOssForTypecho')->userDir;
+ $bucket_name = $options->plugin('AliOssForTypecho')->bucketName;
+ $end_point = ($options->plugin('AliOssForTypecho')->endPoint === "other") ?
+ $options->plugin('AliOssForTypecho')->otherEndPoint :
+ $options->plugin('AliOssForTypecho')->endPoint;
+ $access_id = $options->plugin('AliOssForTypecho')->accessId;
+ $access_key = $options->plugin('AliOssForTypecho')->accessKey;
+
+ $object_name = $userDir . $path;
+
+ $fileSize = strlen($newContent);
+ $ali_options = array(
+ 'content' => $newContent,
+ 'length' => $fileSize,
+ ALIOSS::OSS_HEADERS => array(
+ 'Content-Encoding' => 'utf-8',
+ 'Content-Language' => 'zh-CN',
+ ),
+ );
+
+ $client = new ALIOSS($access_id, $access_key, $end_point);
+ $client->set_enable_domain_style(TRUE);
+
+ $ali_response = $client->upload_file_by_content($bucket_name, $object_name, $ali_options);
+
+ if (200 != $ali_response->status)
+ {
+ return FALSE;
+ } else
+ {
+ $object_url = $ali_response->header["_info"]["url"];
+
+ $ifLoaclSave = $options->plugin('AliOssForTypecho')->ifLoaclSave;
+
+ if ($ifLoaclSave === "1" && !Typecho_Common::isAppEngine())
+ {
+ $localFile = Typecho_Common::url(self::UPLOAD_DIR . $path,
+ defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__);
+ $localPath = dirname($localFile);
+
+ $mkdirSuccess = TRUE;
+ //创建上传目录
+ if (!is_dir($localPath))
+ {
+ if (!self::makeUploadDir($localPath))
+ {
+ $mkdirSuccess = FALSE;
+ }
+ }
+
+ $saveOnServerSuccess = FALSE;
+
+ //保存文件到服务器
+ $error_log_path = self::log_path;
+ if ($mkdirSuccess)
+ {
+
+ $deleteLacalFileSuccess = unlink($localFile);
+ if (!$deleteLacalFileSuccess)
+ {
+ $error_log_path = self::log_path;
+ if (!is_dir($error_log_path))
+ {
+ self::makeUploadDir($error_log_path);
+ }
+ $error = '错误:删除文件失败导致无法修改文件' . "\r\n" .
+ '文件:' . $localFile . "\r\n" .
+ '远程文件:' . $object_url . "\r\n" .
+ '时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
+ error_log($error, 3, $error_log_path . "error.log");
+ } else {
+ if (file_put_contents($localFile, $newContent))
+ {
+ $saveOnServerSuccess = TRUE;
+ } else
+ {
+ $error = '错误:保存文件失败' . "\r\n" .
+ '远程文件:' . $object_url . "\r\n" .
+ '时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
+ error_log($error, 3, $error_log_path . "error.log");
+ }
+ }
+ } else
+ {
+ $error = '错误:创建目录失败' . "\r\n" .
+ '创建路径:' . $localPath . "\r\n" .
+ '远程文件:' . $object_url . "\r\n" .
+ '时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
+ error_log($error, 3, $error_log_path . "error.log");
+ }
+ }
+ }
+
+ //返回相对存储路径
+ return array(
+ 'name' => $content['attachment']->name,
+ 'path' => $path,
+ 'size' => $fileSize,
+ 'type' => $content['attachment']->type,
+ 'mime' => $content['attachment']->mime
+ );
+ }
+
+ /**
+ * 删除文件
+ *
+ * @access public
+ * @param array $content 文件相关信息
+ * @return string
+ */
+ public static function deleteHandle(array $content)
+ {
+ $options = Typecho_Widget::widget('Widget_Options');
+
+ $userDir = $options->plugin('AliOssForTypecho')->userDir;
+ $access_id = $options->plugin('AliOssForTypecho')->accessId;
+ $access_key = $options->plugin('AliOssForTypecho')->accessKey;
+ $bucket_name = $options->plugin('AliOssForTypecho')->bucketName;
+ $end_point = ($options->plugin('AliOssForTypecho')->endPoint === "other") ?
+ $options->plugin('AliOssForTypecho')->otherEndPoint :
+ $options->plugin('AliOssForTypecho')->endPoint;
+ $ali_options = null;
+
+ $client = new ALIOSS($access_id, $access_key, $end_point);
+
+ $path = $content['attachment']->path;
+ $object_name = $userDir . $path;
+ $ali_response = $client->delete_object($bucket_name, $object_name, $ali_options);
+
+ $ifLoaclSave = $options->plugin('AliOssForTypecho')->ifLoaclSave;
+ if ($ifLoaclSave === "1" && !Typecho_Common::isAppEngine())
+ {
+ $localPath = Typecho_Common::url(defined('__TYPECHO_UPLOAD_DIR__') ? __TYPECHO_UPLOAD_DIR__ : self::UPLOAD_DIR,
+ defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__)
+ . $path;
+
+ $deleteLacalFileSuccess = unlink($localPath);
+
+ if (!$deleteLacalFileSuccess)
+ {
+ $error_log_path = self::log_path;
+ if (!is_dir($error_log_path))
+ {
+ self::makeUploadDir($error_log_path);
+ }
+ $error = '错误:删除文件失败' . "\r\n" .
+ '文件:' . $localPath . "\r\n" .
+ '时间:' . date('Y-m-d h:i:sa') . "\r\n\r\n";
+ error_log($error, 3, $error_log_path . "error.log");
+ }
+ }
+ return ($ali_response->status == 200);
+ }
+
+ /**
+ * 获取实际文件绝对访问路径
+ *
+ * @access public
+ * @param array $content 文件相关信息
+ * @return string
+ */
+ public static function attachmentHandle(array $content)
+ {
+ $options = Typecho_Widget::widget('Widget_Options');
+
+ $cdnUrl = $options->plugin('AliOssForTypecho')->cdnUrl;
+ $userDir = $options->plugin('AliOssForTypecho')->userDir;
+ if ($cdnUrl == '')
+ {
+ $bucket_name = $options->plugin('AliOssForTypecho')->bucketName;
+ $end_point = ($options->plugin('AliOssForTypecho')->endPoint === "other") ?
+ $options->plugin('AliOssForTypecho')->otherEndPoint :
+ $options->plugin('AliOssForTypecho')->endPoint;
+ return 'http://' . $bucket_name . '.' . $end_point . '/' . $userDir . $content['attachment']->path;
+ } else
+ {
+ return 'http://' . $cdnUrl . '/' . $userDir . $content['attachment']->path;
+ }
+ }
+
+ /**
+ * 获取实际文件数据
+ *
+ * @access public
+ * @param array $content
+ * @return string
+ */
+ public static function attachmentDataHandle(array $content)
+ {
+ $options = Typecho_Widget::widget('Widget_Options');
+
+ $cdnUrl = $options->plugin('AliOssForTypecho')->cdnUrl;
+ $userDir = $options->plugin('AliOssForTypecho')->userDir;
+ if ($cdnUrl == '')
+ {
+ $bucket_name = $options->plugin('AliOssForTypecho')->bucketName;
+ $end_point = ($options->plugin('AliOssForTypecho')->endPoint === "other") ?
+ $options->plugin('AliOssForTypecho')->otherEndPoint :
+ $options->plugin('AliOssForTypecho')->endPoint;
+ $filePath = 'http://' . $bucket_name . '.' . $end_point . $userDir . $content['attachment']->path;
+ } else
+ {
+ $filePath = 'http://' . $cdnUrl . $userDir . $content['attachment']->path;
+ }
+
+ return file_get_contents($filePath);
+ }
+
+ /**
+ * 检查文件名
+ *
+ * @access private
+ * @param string $ext 扩展名
+ * @return boolean
+ */
+ private static function checkFileType($ext)
+ {
+ $options = Typecho_Widget::widget('Widget_Options');
+ return in_array($ext, $options->allowedAttachmentTypes);
+ }
+
+ /**
+ * 创建上传路径
+ *
+ * @access private
+ * @param string $path 路径
+ * @return boolean
+ */
+ private static function makeUploadDir($path)
+ {
+ $path = preg_replace("/\\\+/", '/', $path);
+ $current = rtrim($path, '/');
+ $last = $current;
+
+ while (!is_dir($current) && false !== strpos($path, '/'))
+ {
+ $last = $current;
+ $current = dirname($current);
+ }
+
+ if ($last == $current)
+ {
+ return true;
+ }
+
+ if (!@mkdir($last))
+ {
+ return false;
+ }
+
+ $stat = @stat($last);
+ $perms = $stat['mode'] & 0007777;
+ @chmod($last, $perms);
+
+ return self::makeUploadDir($path);
+ }
+
+ /**
+ * 获取安全的文件名
+ *
+ * @param string $name
+ * @static
+ * @access private
+ * @return string
+ */
+ private static function getSafeName(&$name)
+ {
+ $name = str_replace(array('"', '<', '>'), '', $name);
+ $name = str_replace('\\', '/', $name);
+ $name = false === strpos($name, '/') ? ('a' . $name) : str_replace('/', '/a', $name);
+ $info = pathinfo($name);
+ $name = substr($info['basename'], 1);
+
+ return isset($info['extension']) ? $info['extension'] : '';
+ }
+}
|