sdk.class.php 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669
  1. <?php
  2. /**
  3. * OSS(Open Storage Services) PHP SDK v1.1.6
  4. */
  5. //设置默认时区
  6. date_default_timezone_set('Asia/Shanghai');
  7. //检测API路径
  8. if(!defined('OSS_API_PATH'))
  9. define('OSS_API_PATH', dirname(__FILE__));
  10. //加载conf.inc.php文件
  11. require_once OSS_API_PATH.DIRECTORY_SEPARATOR.'conf.inc.php';
  12. //加载RequestCore
  13. require_once OSS_API_PATH.DIRECTORY_SEPARATOR.'lib'.DIRECTORY_SEPARATOR.'requestcore'.DIRECTORY_SEPARATOR.'requestcore.class.php';
  14. //加载MimeTypes
  15. require_once OSS_API_PATH.DIRECTORY_SEPARATOR.'util'.DIRECTORY_SEPARATOR.'mimetypes.class.php';
  16. //检测语言包
  17. if(file_exists(OSS_API_PATH.DIRECTORY_SEPARATOR.'lang'.DIRECTORY_SEPARATOR.ALI_LANG.'.inc.php')){
  18. require_once OSS_API_PATH.DIRECTORY_SEPARATOR.'lang'.DIRECTORY_SEPARATOR.ALI_LANG.'.inc.php';
  19. }else{
  20. throw new OSS_Exception(OSS_LANG_FILE_NOT_EXIST);
  21. }
  22. //定义软件名称,版本号等信息
  23. define('OSS_NAME','oss-sdk-php');
  24. define('OSS_VERSION','1.1.6');
  25. define('OSS_BUILD','201210121010245');
  26. define('OSS_AUTHOR', 'xiaobing.meng@alibaba-inc.com');
  27. // EXCEPTIONS
  28. /**
  29. * OSS异常类,继承自基类
  30. */
  31. class OSS_Exception extends Exception {}
  32. //检测get_loaded_extensions函数是否被禁用。由于有些版本把该函数禁用了,所以先检测该函数是否存在。
  33. if(function_exists('get_loaded_extensions')){
  34. //检测curl扩展
  35. $extensions = get_loaded_extensions();
  36. if($extensions){
  37. if(!in_array('curl', $extensions)){
  38. throw new OSS_Exception(OSS_CURL_EXTENSION_MUST_BE_LOAD);
  39. }
  40. }else{
  41. throw new OSS_Exception(OSS_NO_ANY_EXTENSIONS_LOADED);
  42. }
  43. }else{
  44. throw new OSS_Exception('Function get_loaded_extensions has been disabled,Pls check php config.');
  45. }
  46. //CLASS
  47. /**
  48. * OSS基础类
  49. * @author xiaobing.meng@alibaba-inc.com
  50. * @since 2012-05-31
  51. */
  52. class ALIOSS{
  53. /*%******************************************************************************************%*/
  54. // CONSTANTS
  55. /**
  56. * OSS服务地址
  57. */
  58. const DEFAULT_OSS_HOST = 'oss-cn-beijing.aliyuncs.com';
  59. // const DEFAULT_OSS_HOST = 'oss.aliyuncs.com';
  60. //const DEFAULT_OSS_HOST = '10.230.201.90';
  61. /**
  62. * 软件名称
  63. */
  64. const NAME = OSS_NAME;
  65. /**
  66. * OSS软件Build ID
  67. */
  68. const BUILD = OSS_BUILD;
  69. /**
  70. * 版本号
  71. */
  72. const VERSION = OSS_VERSION;
  73. /**
  74. * 作者
  75. */
  76. const AUTHOR = OSS_AUTHOR;
  77. /*%******************************************************************************************%*/
  78. //OSS 内部常量
  79. const OSS_BUCKET = 'bucket';
  80. const OSS_OBJECT = 'object';
  81. const OSS_HEADERS = 'headers';
  82. const OSS_METHOD = 'method';
  83. const OSS_QUERY = 'query';
  84. const OSS_BASENAME = 'basename';
  85. const OSS_MAX_KEYS = 'max-keys';
  86. const OSS_UPLOAD_ID = 'uploadId';
  87. const OSS_MAX_KEYS_VALUE = 100;
  88. const OSS_MAX_OBJECT_GROUP_VALUE = 1000;
  89. const OSS_FILE_SLICE_SIZE = 8192;
  90. const OSS_PREFIX = 'prefix';
  91. const OSS_DELIMITER = 'delimiter';
  92. const OSS_MARKER = 'marker';
  93. const OSS_CONTENT_MD5 = 'Content-Md5';
  94. const OSS_CONTENT_TYPE = 'Content-Type';
  95. const OSS_CONTENT_LENGTH = 'Content-Length';
  96. const OSS_IF_MODIFIED_SINCE = 'If-Modified-Since';
  97. const OSS_IF_UNMODIFIED_SINCE = 'If-Unmodified-Since';
  98. const OSS_IF_MATCH = 'If-Match';
  99. const OSS_IF_NONE_MATCH = 'If-None-Match';
  100. const OSS_CACHE_CONTROL = 'Cache-Control';
  101. const OSS_EXPIRES = 'Expires';
  102. const OSS_PREAUTH = 'preauth';
  103. const OSS_CONTENT_COING = 'Content-Coding';
  104. const OSS_CONTENT_DISPOSTION = 'Content-Disposition';
  105. const OSS_RANGE = 'Range';
  106. const OS_CONTENT_RANGE = 'Content-Range';
  107. const OSS_CONTENT = 'content';
  108. const OSS_BODY = 'body';
  109. const OSS_LENGTH = 'length';
  110. const OSS_HOST = 'Host';
  111. const OSS_DATE = 'Date';
  112. const OSS_AUTHORIZATION = 'Authorization';
  113. const OSS_FILE_DOWNLOAD = 'fileDownload';
  114. const OSS_FILE_UPLOAD = 'fileUpload';
  115. const OSS_PART_SIZE = 'partSize';
  116. const OSS_SEEK_TO = 'seekTo';
  117. const OSS_SIZE = 'size';
  118. const OSS_QUERY_STRING = 'query_string';
  119. const OSS_SUB_RESOURCE = 'sub_resource';
  120. const OSS_DEFAULT_PREFIX = 'x-oss-';
  121. /*%******************************************************************************************%*/
  122. //私有URL变量
  123. const OSS_URL_ACCESS_KEY_ID = 'OSSAccessKeyId';
  124. const OSS_URL_EXPIRES = 'Expires';
  125. const OSS_URL_SIGNATURE = 'Signature';
  126. /*%******************************************************************************************%*/
  127. //HTTP方法
  128. const OSS_HTTP_GET = 'GET';
  129. const OSS_HTTP_PUT = 'PUT';
  130. const OSS_HTTP_HEAD = 'HEAD';
  131. const OSS_HTTP_POST = 'POST';
  132. const OSS_HTTP_DELETE = 'DELETE';
  133. const OSS_HTTP_OPTIONS = 'OPTIONS';
  134. /*%******************************************************************************************%*/
  135. //其他常量
  136. //x-oss
  137. const OSS_ACL = 'x-oss-acl';
  138. //OBJECT GROUP
  139. const OSS_OBJECT_GROUP = 'x-oss-file-group';
  140. //Multi Part
  141. const OSS_MULTI_PART = 'uploads';
  142. //Multi Delete
  143. const OSS_MULTI_DELETE = 'delete';
  144. //OBJECT COPY SOURCE
  145. const OSS_OBJECT_COPY_SOURCE = 'x-oss-copy-source';
  146. //private,only owner
  147. const OSS_ACL_TYPE_PRIVATE = 'private';
  148. //public reand
  149. const OSS_ACL_TYPE_PUBLIC_READ = 'public-read';
  150. //public read write
  151. const OSS_ACL_TYPE_PUBLIC_READ_WRITE = 'public-read-write';
  152. //OSS ACL数组
  153. static $OSS_ACL_TYPES = array(
  154. self::OSS_ACL_TYPE_PRIVATE,
  155. self::OSS_ACL_TYPE_PUBLIC_READ,
  156. self::OSS_ACL_TYPE_PUBLIC_READ_WRITE
  157. );
  158. const OSS_CORS_ALLOWED_ORIGIN='AllowedOrigin';
  159. const OSS_CORS_ALLOWED_METHOD='AllowedMethod';
  160. const OSS_CORS_ALLOWED_HEADER='AllowedHeader';
  161. const OSS_CORS_EXPOSE_HEADER='ExposeHeader';
  162. const OSS_CORS_MAX_AGE_SECONDS='MaxAgeSeconds';
  163. const OSS_OPTIONS_ORIGIN = 'Origin';
  164. const OSS_OPTIONS_REQUEST_METHOD = 'Access-Control-Request-Method';
  165. const OSS_OPTIONS_REQUEST_HEADERS = 'Access-Control-Request-Headers';
  166. /*%******************************************************************************************%*/
  167. // PROPERTIES
  168. /**
  169. * 是否使用SSL
  170. */
  171. protected $use_ssl = false;
  172. /**
  173. * 是否开启debug模式
  174. */
  175. private $debug_mode = true;
  176. /**
  177. * 最大重试次数
  178. */
  179. private $max_retries = 3;
  180. /**
  181. * 已经重试次数
  182. */
  183. private $redirects = 0;
  184. /**
  185. * 虚拟地址
  186. */
  187. private $vhost;
  188. /**
  189. * 路径表现方式
  190. */
  191. private $enable_domain_style = false;
  192. /**
  193. * 请求URL
  194. */
  195. private $request_url;
  196. /**
  197. * OSS API ACCESS ID
  198. */
  199. private $access_id;
  200. /**
  201. * OSS API ACCESS KEY
  202. */
  203. private $access_key;
  204. /**
  205. * hostname
  206. */
  207. private $hostname;
  208. /**
  209. * port number
  210. */
  211. private $port;
  212. /*%******************************************************************************************************%*/
  213. //Constructor
  214. /**
  215. * 默认构造函数
  216. * @param string $_access_id (Optional)
  217. * @param string $access_key (Optional)
  218. * @param string $hostname (Optional)
  219. * @throws OSS_Exception
  220. * @author xiaobing.meng@alibaba-inc.com
  221. * @since 2011-11-08
  222. */
  223. public function __construct($access_id = NULL, $access_key = NULL, $hostname = NULL ){
  224. //验证access_id,access_key
  225. if(!$access_id && !defined('OSS_ACCESS_ID')){
  226. throw new OSS_Exception(NOT_SET_OSS_ACCESS_ID);
  227. }
  228. if(!$access_key && !defined('OSS_ACCESS_KEY')){
  229. throw new OSS_Exception(NOT_SET_OSS_ACCESS_KEY);
  230. }
  231. if($access_id && $access_key){
  232. $this->access_id = $access_id;
  233. $this->access_key = $access_key;
  234. }elseif (defined('OSS_ACCESS_ID') && defined('OSS_ACCESS_KEY')){
  235. $this->access_id = OSS_ACCESS_ID;
  236. $this->access_key = OSS_ACCESS_KEY;
  237. }else{
  238. throw new OSS_Exception(NOT_SET_OSS_ACCESS_ID_AND_ACCESS_KEY);
  239. }
  240. //校验access_id&access_key
  241. if(empty($this->access_id) || empty($this->access_key)){
  242. throw new OSS_Exception(OSS_ACCESS_ID_OR_ACCESS_KEY_EMPTY);
  243. }
  244. //校验hostname
  245. if(NULL === $hostname){
  246. $this->hostname = self::DEFAULT_OSS_HOST;
  247. }else{
  248. $this->hostname = $hostname;
  249. }
  250. }
  251. /*%******************************************************************************************************%*/
  252. //属性
  253. /**
  254. * 设置debug模式
  255. * @param boolean $debug_mode (Optional)
  256. * @author xiaobing.meng@alibaba-inc.com
  257. * @since 2012-05-29
  258. * @return void
  259. */
  260. public function set_debug_mode($debug_mode = true){
  261. $this->debug_mode = $debug_mode;
  262. }
  263. /**
  264. * 设置最大尝试次数
  265. * @param int $max_retries
  266. * @author xiaobing.meng@alibaba-inc.com
  267. * @since 2012-05-29
  268. * @return void
  269. */
  270. public function set_max_retries($max_retries = 3){
  271. $this->max_retries = $max_retries;
  272. }
  273. /**
  274. * 获取最大尝试次数
  275. * @author xiaobing.meng@alibaba-inc.com
  276. * @since 2012-05-29
  277. * @return int
  278. */
  279. public function get_max_retries(){
  280. return $this->max_retries;
  281. }
  282. /**
  283. * 设置host地址
  284. * @author xiaobing.meng@alibaba-inc.com
  285. * @param string $hostname host name
  286. * @param int $port int
  287. * @since 2012-06-11
  288. * @return void
  289. */
  290. public function set_host_name($hostname, $port = null){
  291. $this->hostname = $hostname;
  292. if($port){
  293. $this->port = $port;
  294. $this->hostname .= ':'.$port;
  295. }
  296. }
  297. /**
  298. * 设置vhost地址
  299. * @author xiaobing.meng@alibaba-inc.com
  300. * @param string $vhost vhost
  301. * @since 2012-06-11
  302. * @return void
  303. */
  304. public function set_vhost($vhost){
  305. $this->vhost = $vhost;
  306. }
  307. /**
  308. * 设置路径形式,如果为true,则启用三级域名,如bucket.oss.aliyuncs.com
  309. * @author xiaobing.meng@alibaba-inc.com
  310. * @param boolean $enable_domain_style
  311. * @since 2012-06-11
  312. * @return void
  313. */
  314. public function set_enable_domain_style($enable_domain_style = true){
  315. $this->enable_domain_style = $enable_domain_style;
  316. }
  317. /*%******************************************************************************************************%*/
  318. //请求
  319. /**
  320. * Authorization
  321. * @param array $options (Required)
  322. * @throws OSS_Exception
  323. * @author xiaobing.meng@alibaba-inc.com
  324. * @since 2012-05-31
  325. */
  326. public function auth($options){
  327. //开始记录LOG
  328. $msg = "---LOG START---------------------------------------------------------------------------\n";
  329. //验证Bucket,list_bucket时不需要验证
  330. if(!( ('/' == $options[self::OSS_OBJECT]) && ('' == $options[self::OSS_BUCKET]) && ('GET' == $options[self::OSS_METHOD])) && !$this->validate_bucket($options[self::OSS_BUCKET])){
  331. throw new OSS_Exception('"'.$options[self::OSS_BUCKET].'"'.OSS_BUCKET_NAME_INVALID);
  332. }
  333. //验证Object
  334. if(isset($options[self::OSS_OBJECT]) && !$this->validate_object($options[self::OSS_OBJECT])){
  335. throw new OSS_Exception($options[self::OSS_OBJECT].OSS_OBJECT_NAME_INVALID);
  336. }
  337. //Object编码为UTF-8
  338. if($this->is_gb2312($options[self::OSS_OBJECT])){
  339. $options[self::OSS_OBJECT] = iconv('GB2312', "UTF-8",$options[self::OSS_OBJECT]);
  340. }elseif($this->check_char($options[self::OSS_OBJECT],true)){
  341. $options[self::OSS_OBJECT] = iconv('GBK', "UTF-8",$options[self::OSS_OBJECT]);
  342. }
  343. //验证ACL
  344. if(isset($options[self::OSS_HEADERS][self::OSS_ACL]) && !empty($options[self::OSS_HEADERS][self::OSS_ACL])){
  345. if(!in_array(strtolower($options[self::OSS_HEADERS][self::OSS_ACL]), self::$OSS_ACL_TYPES)){
  346. throw new OSS_Exception($options[self::OSS_HEADERS][self::OSS_ACL].':'.OSS_ACL_INVALID);
  347. }
  348. }
  349. //定义scheme
  350. $scheme = $this->use_ssl ? 'https://' : 'http://';
  351. if($this->enable_domain_style){
  352. $hostname = $this->vhost ? $this->vhost : (($options[self::OSS_BUCKET] =='')?$this->hostname:($options[self::OSS_BUCKET].'.').$this->hostname);
  353. }else{
  354. $hostname = (isset($options[self::OSS_BUCKET]) && ''!==$options[self::OSS_BUCKET])?$this->hostname.'/'.$options[self::OSS_BUCKET]:$this->hostname;
  355. }
  356. //请求参数
  357. $resource = '';
  358. $sub_resource = '';
  359. $signable_resource = '';
  360. $query_string_params = array();
  361. $signable_query_string_params = array();
  362. $string_to_sign = '';
  363. $headers = array (
  364. self::OSS_CONTENT_MD5 => '',
  365. self::OSS_CONTENT_TYPE => isset($options[self::OSS_CONTENT_TYPE])?$options[self::OSS_CONTENT_TYPE]:'application/x-www-form-urlencoded',
  366. self::OSS_DATE => isset($options[self::OSS_DATE])? $options[self::OSS_DATE]: gmdate('D, d M Y H:i:s \G\M\T'),
  367. self::OSS_HOST => $this->enable_domain_style?$hostname:$this->hostname,
  368. );
  369. if(isset ( $options [self::OSS_OBJECT] ) && '/' !== $options [self::OSS_OBJECT]){
  370. //$options[self::OSS_OBJECT] = $this->replace_invalid_xml_char($options[self::OSS_OBJECT]);
  371. $signable_resource = '/'.str_replace(array('%2F','%25'),array('/','%'), rawurlencode($options[self::OSS_OBJECT]));
  372. }
  373. if(isset($options[self::OSS_QUERY_STRING])){
  374. $query_string_params = array_merge($query_string_params,$options[self::OSS_QUERY_STRING]);
  375. }
  376. $query_string = $this->to_query_string($query_string_params);
  377. $signable_list = array(
  378. 'partNumber',
  379. 'uploadId',
  380. );
  381. foreach ($signable_list as $item){
  382. if(isset($options[$item])){
  383. $signable_query_string_params[$item] = $options[$item];
  384. }
  385. }
  386. $signable_query_string = $this->to_query_string($signable_query_string_params);
  387. //合并 HTTP headers
  388. if (isset ( $options [self::OSS_HEADERS] )) {
  389. $headers = array_merge ( $headers, $options [self::OSS_HEADERS] );
  390. }
  391. //生成请求URL
  392. $conjunction = '?';
  393. $non_signable_resource = '';
  394. if (isset($options[self::OSS_SUB_RESOURCE])){
  395. $signable_resource .= $conjunction . $options[self::OSS_SUB_RESOURCE];
  396. $conjunction = '&';
  397. }
  398. if($signable_query_string !== ''){
  399. $signable_query_string = $conjunction.$signable_query_string;
  400. $conjunction = '&';
  401. }
  402. if($query_string !== ''){
  403. $non_signable_resource .= $conjunction . $query_string;
  404. $conjunction = '&';
  405. }
  406. $this->request_url = $scheme . $hostname . $signable_resource . $signable_query_string . $non_signable_resource;
  407. $msg .= "--REQUEST URL:----------------------------------------------\n".$this->request_url."\n";
  408. //创建请求
  409. $request = new RequestCore($this->request_url);
  410. // Streaming uploads
  411. if (isset($options[self::OSS_FILE_UPLOAD])){
  412. if (is_resource($options[self::OSS_FILE_UPLOAD])){
  413. $length = null;
  414. if (isset($options[self::OSS_CONTENT_LENGTH])){
  415. $length = $options[self::OSS_CONTENT_LENGTH];
  416. }elseif (isset($options[self::OSS_SEEK_TO])){
  417. $stats = fstat($options[self::OSS_FILE_UPLOAD]);
  418. if ($stats && $stats[self::OSS_SIZE] >= 0){
  419. $length = $stats[self::OSS_SIZE] - (integer) $options[self::OSS_SEEK_TO];
  420. }
  421. }
  422. $request->set_read_stream($options[self::OSS_FILE_UPLOAD], $length);
  423. if ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded'){
  424. $headers[self::OSS_CONTENT_TYPE] = 'application/octet-stream';
  425. }
  426. }else{
  427. $request->set_read_file($options[self::OSS_FILE_UPLOAD]);
  428. $length = $request->read_stream_size;
  429. if (isset($options[self::OSS_CONTENT_LENGTH])){
  430. $length = $options[self::OSS_CONTENT_LENGTH];
  431. }elseif (isset($options[self::OSS_SEEK_TO]) && isset($length)){
  432. $length -= (integer) $options[self::OSS_SEEK_TO];
  433. }
  434. $request->set_read_stream_size($length);
  435. if (isset($headers[self::OSS_CONTENT_TYPE]) && ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded')){
  436. $extension = explode('.', $options[self::OSS_FILE_UPLOAD]);
  437. $extension = array_pop($extension);
  438. $mime_type = MimeTypes::get_mimetype($extension);
  439. $headers[self::OSS_CONTENT_TYPE] = $mime_type;
  440. }
  441. }
  442. $options[self::OSS_CONTENT_MD5] = '';
  443. }
  444. if (isset($options[self::OSS_SEEK_TO])){
  445. $request->set_seek_position((integer) $options[self::OSS_SEEK_TO]);
  446. }
  447. if (isset($options[self::OSS_FILE_DOWNLOAD])){
  448. if (is_resource($options[self::OSS_FILE_DOWNLOAD])){
  449. $request->set_write_stream($options[self::OSS_FILE_DOWNLOAD]);
  450. }else{
  451. $request->set_write_file($options[self::OSS_FILE_DOWNLOAD]);
  452. }
  453. }
  454. if(isset($options[self::OSS_METHOD])){
  455. $request->set_method($options[self::OSS_METHOD]);
  456. $string_to_sign .= $options[self::OSS_METHOD] . "\n";
  457. }
  458. if (isset ( $options [self::OSS_CONTENT] )) {
  459. $request->set_body ( $options [self::OSS_CONTENT] );
  460. if ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded'){
  461. $headers[self::OSS_CONTENT_TYPE] = 'application/octet-stream';
  462. }
  463. $headers[self::OSS_CONTENT_LENGTH] = strlen($options [self::OSS_CONTENT]);
  464. $headers[self::OSS_CONTENT_MD5] = $this->hex_to_base64(md5($options[self::OSS_CONTENT]));
  465. }
  466. uksort($headers, 'strnatcasecmp');
  467. foreach ( $headers as $header_key => $header_value ) {
  468. $header_value = str_replace ( array ("\r", "\n" ), '', $header_value );
  469. if ($header_value !== '') {
  470. $request->add_header ( $header_key, $header_value );
  471. }
  472. if (
  473. strtolower($header_key) === 'content-md5' ||
  474. strtolower($header_key) === 'content-type' ||
  475. strtolower($header_key) === 'date' ||
  476. (isset($options['self::OSS_PREAUTH']) && (integer) $options['self::OSS_PREAUTH'] > 0)
  477. ){
  478. $string_to_sign .= $header_value . "\n";
  479. }elseif (substr(strtolower($header_key), 0, 6) === self::OSS_DEFAULT_PREFIX){
  480. $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
  481. }
  482. }
  483. $string_to_sign .= '/' . $options[self::OSS_BUCKET];
  484. $string_to_sign .= $this->enable_domain_style ? ($options[self::OSS_BUCKET]!=''? ($options[self::OSS_OBJECT]=='/'?'/':'') :'' ) : '';
  485. $string_to_sign .= rawurldecode($signable_resource) . urldecode($signable_query_string);
  486. $msg .= "STRING TO SIGN:----------------------------------------------\n".$string_to_sign."\n";
  487. $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->access_key, true));
  488. $request->add_header('Authorization', 'OSS ' . $this->access_id . ':' . $signature);
  489. if (isset($options[self::OSS_PREAUTH]) && (integer) $options[self::OSS_PREAUTH] > 0){
  490. return $this->request_url . $conjunction . self::OSS_URL_ACCESS_KEY_ID.'=' . $this->access_id . '&'.self::OSS_URL_EXPIRES.'=' . $options[self::OSS_PREAUTH] . '&'.self::OSS_URL_SIGNATURE.'=' . rawurlencode($signature);
  491. }elseif (isset($options[self::OSS_PREAUTH])){
  492. return $this->request_url;
  493. }
  494. if ($this->debug_mode){
  495. $request->debug_mode = $this->debug_mode;
  496. }
  497. $msg .= "REQUEST HEADERS:----------------------------------------------\n".serialize($request->request_headers)."\n";
  498. $request->send_request();
  499. $response_header = $request->get_response_header();
  500. $response_header['x-oss-request-url'] = $this->request_url;
  501. $response_header['x-oss-redirects'] = $this->redirects;
  502. $response_header['x-oss-stringtosign'] = $string_to_sign;
  503. $response_header['x-oss-requestheaders'] = $request->request_headers;
  504. $msg .= "RESPONSE HEADERS:----------------------------------------------\n".serialize($response_header)."\n";
  505. $data = new ResponseCore ( $response_header , $request->get_response_body (), $request->get_response_code () );
  506. if((integer)$request->get_response_code() === 400 /*Bad Request*/ || (integer)$request->get_response_code() === 500 /*Internal Error*/ || (integer)$request->get_response_code() === 503 /*Service Unavailable*/){
  507. if($this->redirects <= $this->max_retries ){
  508. //设置休眠
  509. $delay = (integer) (pow(4, $this->redirects) * 100000);
  510. usleep($delay);
  511. $this->redirects++;
  512. $data = $this->auth($options);
  513. }
  514. }
  515. $msg .= "RESPONSE DATA:----------------------------------------------\n".serialize($data)."\n";
  516. $msg .= date('Y-m-d H:i:s').":---LOG END---------------------------------------------------------------------------\n";
  517. //add log
  518. $this->log($msg);
  519. $this->redirects = 0;
  520. return $data;
  521. }
  522. /*%******************************************************************************************************%*/
  523. //Service Operation
  524. /**
  525. * Get Bucket list
  526. * @param array $options (Optional)
  527. * @throws OSS_Exception
  528. * @author xiaobing.meng@alibaba-inc.com
  529. * @since 2011-11-14
  530. * @return ResponseCore
  531. */
  532. public function list_bucket($options = NULL) {
  533. //$options
  534. $this->validate_options($options);
  535. if (! $options) {
  536. $options = array ();
  537. }
  538. $options[self::OSS_BUCKET] = '';
  539. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  540. $options[self::OSS_OBJECT] = '/';
  541. $response = $this->auth ( $options );
  542. return $response;
  543. }
  544. /*%******************************************************************************************************%*/
  545. //Bucket Operation
  546. /**
  547. * Create Bucket
  548. * @param string $bucket (Required)
  549. * @param string $acl (Optional)
  550. * @param array $options (Optional)
  551. * @author xiaobing.meng@alibaba-inc.com
  552. * @since 2011-11-14
  553. * @return ResponseCore
  554. */
  555. public function create_bucket($bucket, $acl = self::OSS_ACL_TYPE_PRIVATE, $options = NULL){
  556. //$options
  557. $this->validate_options($options);
  558. if (! $options) {
  559. $options = array ();
  560. }
  561. //bucket
  562. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  563. $options[self::OSS_BUCKET] = $bucket;
  564. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  565. $options[self::OSS_OBJECT] = '/';
  566. $options[self::OSS_HEADERS] = array(self::OSS_ACL => $acl);
  567. $response = $this->auth ( $options );
  568. return $response;
  569. }
  570. /**
  571. * Delete Bucket
  572. * @param string $bucket (Required)
  573. * @param array $options (Optional)
  574. * @author xiaobing.meng@alibaba-inc.com
  575. * @since 2011-11-14
  576. * @return ResponseCore
  577. */
  578. public function delete_bucket($bucket, $options = NULL){
  579. //$options
  580. $this->validate_options($options);
  581. if (! $options) {
  582. $options = array ();
  583. }
  584. //bucket
  585. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  586. $options[self::OSS_BUCKET] = $bucket;
  587. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  588. $options[self::OSS_OBJECT] = '/';
  589. $response = $this->auth ( $options );
  590. return $response;
  591. }
  592. /**
  593. * Get Bucket's ACL
  594. * @param string $bucket (Required)
  595. * @param array $options (Optional)
  596. * @throws OSS_Exception
  597. * @author xiaobing.meng@alibaba-inc.com
  598. * @since 2011-11-14
  599. * @return ResponseCore
  600. */
  601. public function get_bucket_acl($bucket, $options = NULL){
  602. //options
  603. $this->validate_options($options);
  604. if(!$options){
  605. $options = array();
  606. }
  607. //bucket
  608. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  609. $options[self::OSS_BUCKET] = $bucket;
  610. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  611. $options[self::OSS_OBJECT] = '/';
  612. $options[self::OSS_SUB_RESOURCE] = 'acl';
  613. $response = $this->auth ( $options );
  614. return $response;
  615. }
  616. /**
  617. * Set Bucket'ACL
  618. * @param string $bucket (Required)
  619. * @param string $acl (Required)
  620. * @param array $options (Optional)
  621. * @throws OSS_Exception
  622. * @author xiaobing.meng@alibaba-inc.com
  623. * @since 2011-11-14
  624. * @return ResponseCore
  625. */
  626. public function set_bucket_acl($bucket, $acl, $options = NULL){
  627. //options
  628. $this->validate_options($options);
  629. if(!$options){
  630. $options = array();
  631. }
  632. //bucket
  633. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  634. $options[self::OSS_BUCKET] = $bucket;
  635. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  636. $options[self::OSS_OBJECT] = '/';
  637. $options[self::OSS_HEADERS] = array(self::OSS_ACL => $acl);
  638. $response = $this->auth ( $options );
  639. return $response;
  640. }
  641. /**
  642. * Get Bucket's Logging
  643. * @param string $bucket (Required)
  644. * @param array $options (Optional)
  645. * @throws OSS_Exception
  646. * @author lijie.ma@alibaba-inc.com
  647. * @since 2014-05-04
  648. * @return ResponseCore
  649. */
  650. public function get_bucket_logging($bucket, $options = NULL){
  651. //options
  652. $this->validate_options($options);
  653. if(!$options){
  654. $options = array();
  655. }
  656. //bucket
  657. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  658. $options[self::OSS_BUCKET] = $bucket;
  659. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  660. $options[self::OSS_OBJECT] = '/';
  661. $options[self::OSS_SUB_RESOURCE] = 'logging';
  662. $response = $this->auth ($options);
  663. return $response;
  664. }
  665. /**
  666. * Set Bucket's Logging
  667. * @param string $bucket (Required)
  668. * @param string $target_bucket (Required)
  669. * @param string $target_prefix (Optional)
  670. * @param array $options (Optional)
  671. * @throws OSS_Exception
  672. * @author lijie.ma@alibaba-inc.com
  673. * @since 2014-05-04
  674. * @return ResponseCore
  675. */
  676. public function set_bucket_logging($bucket, $target_bucket, $target_prefix, $options = NULL){
  677. //options
  678. $this->validate_options($options);
  679. if(!$options){
  680. $options = array();
  681. }
  682. //bucket
  683. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  684. $this->is_empty($target_bucket,OSS_TARGET_BUCKET_IS_NOT_ALLOWED_EMPTY);
  685. $options[self::OSS_BUCKET] = $bucket;
  686. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  687. $options[self::OSS_OBJECT] = '/';
  688. $options[self::OSS_SUB_RESOURCE] = 'logging';
  689. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  690. $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><BucketLoggingStatus></BucketLoggingStatus>');
  691. $logging_enabled_part=$xml->addChild('LoggingEnabled');
  692. $logging_enabled_part->addChild('TargetBucket', $target_bucket);
  693. $logging_enabled_part->addChild('TargetPrefix', $target_prefix);
  694. $options[self::OSS_CONTENT] = $xml->asXML();
  695. echo $xml->asXML();
  696. return $this->auth($options);
  697. }
  698. /**
  699. * Delete Bucket's Logging
  700. * @param string $bucket (Required)
  701. * @param array $options (Optional)
  702. * @throws OSS_Exception
  703. * @author lijie.ma@alibaba-inc.com
  704. * @since 2014-05-04
  705. * @return ResponseCore
  706. */
  707. public function delete_bucket_logging($bucket, $options = NULL){
  708. //options
  709. $this->validate_options($options);
  710. if(!$options){
  711. $options = array();
  712. }
  713. //bucket
  714. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  715. $options[self::OSS_BUCKET] = $bucket;
  716. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  717. $options[self::OSS_OBJECT] = '/';
  718. $options[self::OSS_SUB_RESOURCE] = 'logging';
  719. $response = $this->auth ($options);
  720. return $response;
  721. }
  722. /**
  723. * Set Bucket's Website
  724. * @param string $bucket (Required)
  725. * @param string $index_document (Required)
  726. * @param string $error_document (Optional)
  727. * @param array $options (Optional)
  728. * @throws OSS_Exception
  729. * @author lijie.ma@alibaba-inc.com
  730. * @since 2014-05-04
  731. * @return ResponseCore
  732. */
  733. public function set_bucket_website($bucket, $index_document, $error_document, $options = NULL){
  734. //options
  735. $this->validate_options($options);
  736. if(!$options){
  737. $options = array();
  738. }
  739. //bucket
  740. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  741. $this->is_empty($index_document,OSS_INDEX_DOCUMENT_IS_NOT_ALLOWED_EMPTY);
  742. $options[self::OSS_BUCKET] = $bucket;
  743. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  744. $options[self::OSS_OBJECT] = '/';
  745. $options[self::OSS_SUB_RESOURCE] = 'website';
  746. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  747. $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><WebsiteConfiguration></WebsiteConfiguration>');
  748. $index_document_part=$xml->addChild('IndexDocument');
  749. $error_document_part=$xml->addChild('ErrorDocument');
  750. $index_document_part->addChild('Suffix', $index_document);
  751. $error_document_part->addChild('Key', $error_document);
  752. $options[self::OSS_CONTENT] = $xml->asXML();
  753. echo $xml->asXML();
  754. return $this->auth($options);
  755. }
  756. /**
  757. * Get Bucket's Website
  758. * @param string $bucket (Required)
  759. * @param array $options (Optional)
  760. * @throws OSS_Exception
  761. * @author lijie.ma@alibaba-inc.com
  762. * @since 2014-05-04
  763. * @return ResponseCore
  764. */
  765. public function get_bucket_website($bucket, $options = NULL){
  766. //options
  767. $this->validate_options($options);
  768. if(!$options){
  769. $options = array();
  770. }
  771. //bucket
  772. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  773. $options[self::OSS_BUCKET] = $bucket;
  774. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  775. $options[self::OSS_OBJECT] = '/';
  776. $options[self::OSS_SUB_RESOURCE] = 'website';
  777. $response = $this->auth ($options);
  778. return $response;
  779. }
  780. /**
  781. * Delete Bucket's Website
  782. * @param string $bucket (Required)
  783. * @param array $options (Optional)
  784. * @throws OSS_Exception
  785. * @author lijie.ma@alibaba-inc.com
  786. * @since 2014-05-04
  787. * @return ResponseCore
  788. */
  789. public function delete_bucket_website($bucket, $options = NULL){
  790. //options
  791. $this->validate_options($options);
  792. if(!$options){
  793. $options = array();
  794. }
  795. //bucket
  796. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  797. $options[self::OSS_BUCKET] = $bucket;
  798. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  799. $options[self::OSS_OBJECT] = '/';
  800. $options[self::OSS_SUB_RESOURCE] = 'website';
  801. $response = $this->auth ($options);
  802. return $response;
  803. }
  804. /**
  805. * Set Bucket's Cors
  806. * @param string $bucket (Required)
  807. * @param array $cors_rules (Required)
  808. * @param array $options (Optional)
  809. * @throws OSS_Exception
  810. * @author lijie.ma@alibaba-inc.com
  811. * @since 2014-05-04
  812. * @return ResponseCore
  813. */
  814. public function set_bucket_cors($bucket, $cors_rules, $options = NULL){
  815. //options
  816. $this->validate_options($options);
  817. if(!$options){
  818. $options = array();
  819. }
  820. //bucket
  821. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  822. $options[self::OSS_BUCKET] = $bucket;
  823. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  824. $options[self::OSS_OBJECT] = '/';
  825. $options[self::OSS_SUB_RESOURCE] = 'cors';
  826. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  827. $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><CORSConfiguration></CORSConfiguration>');
  828. foreach ($cors_rules as $cors_rule){
  829. $cors_rule_part = $xml->addChild('CORSRule');
  830. foreach ($cors_rule[self::OSS_CORS_ALLOWED_ORIGIN] as $value){
  831. $cors_rule_part->addChild(self::OSS_CORS_ALLOWED_ORIGIN, $value);
  832. }
  833. foreach ($cors_rule[self::OSS_CORS_ALLOWED_HEADER] as $value){
  834. $cors_rule_part->addChild(self::OSS_CORS_ALLOWED_HEADER, $value);
  835. }
  836. foreach ($cors_rule[self::OSS_CORS_ALLOWED_METHOD] as $value){
  837. $cors_rule_part->addChild(self::OSS_CORS_ALLOWED_METHOD, $value);
  838. }
  839. foreach ($cors_rule[self::OSS_CORS_EXPOSE_HEADER] as $value){
  840. $cors_rule_part->addChild(self::OSS_CORS_EXPOSE_HEADER, $value);
  841. }
  842. $cors_rule_part->addChild(self::OSS_CORS_MAX_AGE_SECONDS, $cors_rule[self::OSS_CORS_MAX_AGE_SECONDS]);
  843. }
  844. $options[self::OSS_CONTENT] = $xml->asXML();
  845. return $this->auth($options);
  846. }
  847. /**
  848. * Get Bucket's Cors
  849. * @param string $bucket (Required)
  850. * @param array $options (Optional)
  851. * @throws OSS_Exception
  852. * @author lijie.ma@alibaba-inc.com
  853. * @since 2014-05-04
  854. * @return ResponseCore
  855. */
  856. public function get_bucket_cors($bucket, $options = NULL){
  857. //options
  858. $this->validate_options($options);
  859. if(!$options){
  860. $options = array();
  861. }
  862. //bucket
  863. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  864. $options[self::OSS_BUCKET] = $bucket;
  865. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  866. $options[self::OSS_OBJECT] = '/';
  867. $options[self::OSS_SUB_RESOURCE] = 'cors';
  868. $response = $this->auth ($options);
  869. return $response;
  870. }
  871. /**
  872. * Delete Bucket's Cors
  873. * @param string $bucket (Required)
  874. * @param array $options (Optional)
  875. * @throws OSS_Exception
  876. * @author lijie.ma@alibaba-inc.com
  877. * @since 2014-05-04
  878. * @return ResponseCore
  879. */
  880. public function delete_bucket_cors($bucket, $options = NULL){
  881. //options
  882. $this->validate_options($options);
  883. if(!$options){
  884. $options = array();
  885. }
  886. //bucket
  887. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  888. $options[self::OSS_BUCKET] = $bucket;
  889. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  890. $options[self::OSS_OBJECT] = '/';
  891. $options[self::OSS_SUB_RESOURCE] = 'cors';
  892. $response = $this->auth ($options);
  893. return $response;
  894. }
  895. /**
  896. * Options Object
  897. * @param string $bucket (Required)
  898. * @param array $options_request (Required)
  899. * @param array $options (Optional)
  900. * @throws OSS_Exception
  901. * @author xiaobing.meng@alibaba-inc.com
  902. * @since 2011-11-14
  903. * @return ResponseCore
  904. */
  905. public function options_object($bucket, $object, $origin, $request_method, $request_headers, $options = NULL){
  906. //options
  907. $this->validate_options($options);
  908. if(!$options){
  909. $options = array();
  910. }
  911. //bucket
  912. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  913. $options[self::OSS_BUCKET] = $bucket;
  914. $options[self::OSS_METHOD] = self::OSS_HTTP_OPTIONS;
  915. $options[self::OSS_OBJECT] = $object;
  916. $options[self::OSS_HEADERS] = array(self::OSS_OPTIONS_ORIGIN => $origin, self::OSS_OPTIONS_REQUEST_HEADERS => $request_headers, self::OSS_OPTIONS_REQUEST_METHOD => $request_method);
  917. $response = $this->auth ( $options );
  918. return $response;
  919. }
  920. /*%******************************************************************************************************%*/
  921. //Object Operation
  922. /**
  923. * List Object
  924. * @param string $bucket (Required)
  925. * @param array $options (Optional)
  926. * 其中options中的参数如下
  927. * $options = array(
  928. * 'max-keys' => max-keys用于限定此次返回object的最大数,如果不设定,默认为100,max-keys取值不能大于100。
  929. * 'prefix' => 限定返回的object key必须以prefix作为前缀。注意使用prefix查询时,返回的key中仍会包含prefix。
  930. * 'delimiter' => 是一个用于对Object名字进行分组的字符。所有名字包含指定的前缀且第一次出现delimiter字符之间的object作为一组元素
  931. * 'marker' => 用户设定结果从marker之后按字母排序的第一个开始返回。
  932. * )
  933. * 其中 prefix,marker用来实现分页显示效果,参数的长度必须小于256字节。
  934. * @throws OSS_Exception
  935. * @author xiaobing.meng@alibaba-inc.com
  936. * @since 2011-11-14
  937. * @return ResponseCore
  938. */
  939. public function list_object($bucket, $options = NULL){
  940. //options
  941. $this->validate_options($options);
  942. if(!$options){
  943. $options = array();
  944. }
  945. //bucket
  946. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  947. $options[self::OSS_BUCKET] = $bucket;
  948. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  949. $options[self::OSS_OBJECT] = '/';
  950. $options[self::OSS_HEADERS] = array(
  951. self::OSS_DELIMITER => isset($options[self::OSS_DELIMITER])?$options[self::OSS_DELIMITER]:'/',
  952. self::OSS_PREFIX => isset($options[self::OSS_PREFIX])?$options[self::OSS_PREFIX]:'',
  953. self::OSS_MAX_KEYS => isset($options[self::OSS_MAX_KEYS])?$options[self::OSS_MAX_KEYS]:self::OSS_MAX_KEYS_VALUE,
  954. self::OSS_MARKER => isset($options[self::OSS_MARKER])?$options[self::OSS_MARKER]:'',
  955. );
  956. $response = $this->auth ( $options );
  957. return $response;
  958. }
  959. /**
  960. * 创建目录(目录和文件的区别在于,目录最后增加'/')
  961. * @param string $bucket
  962. * @param string $object
  963. * @param array $options
  964. * @author xiaobing.meng@alibaba-inc.com
  965. * @since 2011-11-14
  966. * @return ResponseCore
  967. */
  968. public function create_object_dir($bucket, $object, $options = NULL){
  969. //options
  970. $this->validate_options($options);
  971. if(!$options){
  972. $options = array();
  973. }
  974. //bucket
  975. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  976. //object
  977. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  978. $options[self::OSS_BUCKET] = $bucket;
  979. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  980. $options[self::OSS_OBJECT] = $object.'/'; //虚拟目录需要以'/结尾'
  981. $options[self::OSS_CONTENT_LENGTH] = array(self::OSS_CONTENT_LENGTH => 0);
  982. $response = $this->auth ( $options );
  983. return $response;
  984. }
  985. /**
  986. * 通过在http body中添加内容来上传文件,适合比较小的文件
  987. * 根据api约定,需要在http header中增加content-length字段
  988. * @param string $bucket (Required)
  989. * @param string $object (Required)
  990. * @param string $content (Required)
  991. * @param array $options (Optional)
  992. * @author xiaobing.meng@alibaba-inc.com
  993. * @since 2011-11-14
  994. * @return ResponseCore
  995. */
  996. public function upload_file_by_content($bucket, $object, $options = NULL){
  997. //options
  998. $this->validate_options($options);
  999. if(!$options){
  1000. $options = array();
  1001. }
  1002. //bucket
  1003. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1004. //object
  1005. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1006. //内容校验
  1007. $this->validate_content($options);
  1008. $objArr = explode('/', $object);
  1009. $basename = array_pop($objArr);
  1010. $extension = explode ( '.', $basename );
  1011. $extension = array_pop ( $extension );
  1012. $content_type = MimeTypes::get_mimetype(strtolower($extension));
  1013. $options[self::OSS_BUCKET] = $bucket;
  1014. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  1015. $options[self::OSS_OBJECT] = $object;
  1016. if(!isset($options[self::OSS_LENGTH])){
  1017. $options[self::OSS_CONTENT_LENGTH] = strlen($options[self::OSS_CONTENT]);
  1018. }else{
  1019. $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
  1020. }
  1021. if(!isset($options[self::OSS_CONTENT_TYPE]) && isset($content_type) && !empty($content_type) ){
  1022. $options[self::OSS_CONTENT_TYPE] = $content_type;
  1023. }
  1024. $response = $this->auth ( $options );
  1025. return $response;
  1026. }
  1027. /**
  1028. * 上传文件,适合比较大的文件
  1029. * @param string $bucket (Required)
  1030. * @param string $object (Required)
  1031. * @param string $file (Required)
  1032. * @param array $options (Optional)
  1033. * @author xiaobing.meng@alibaba-inc.com
  1034. * @since 2012-02-28
  1035. * @return ResponseCore
  1036. */
  1037. public function upload_file_by_file($bucket, $object, $file, $options = NULL){
  1038. //options
  1039. $this->validate_options($options);
  1040. if(!$options){
  1041. $options = array();
  1042. }
  1043. //bucket
  1044. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1045. //object
  1046. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1047. //file
  1048. $this->is_empty($file, OSS_FILE_PATH_IS_NOT_ALLOWED_EMPTY);
  1049. if($this->chk_chinese($file)){
  1050. $file = iconv('utf-8','gbk',$file);
  1051. }
  1052. $options[self::OSS_FILE_UPLOAD] = $file;
  1053. if(!file_exists($options[self::OSS_FILE_UPLOAD])){
  1054. throw new OSS_Exception($options[self::OSS_FILE_UPLOAD].OSS_FILE_NOT_EXIST);
  1055. }
  1056. $filesize = filesize($options[self::OSS_FILE_UPLOAD]);
  1057. $partsize = 1024 * 1024 ; //默认为 1M
  1058. $extension = explode ( '.', $file );
  1059. $extension = array_pop ( $extension );
  1060. $content_type = MimeTypes::get_mimetype(strtolower($extension));
  1061. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  1062. $options[self::OSS_BUCKET] = $bucket;
  1063. $options[self::OSS_OBJECT] = $object;
  1064. $options[self::OSS_CONTENT_TYPE] = $content_type;
  1065. $options[self::OSS_CONTENT_LENGTH] = $filesize;
  1066. $response = $this->auth($options);
  1067. return $response;
  1068. }
  1069. /**
  1070. * 拷贝Object
  1071. * @param string $bucket (Required)
  1072. * @param string $from_object (Required)
  1073. * @param string $to_object (Required)
  1074. * @param string $options (Optional)
  1075. * @author xiaobing.meng@alibaba-inc.com
  1076. * @since 2011-12-21
  1077. * @return ResponseCore
  1078. */
  1079. public function copy_object($from_bucket, $from_object, $to_bucket, $to_object, $options = NULL){
  1080. //options
  1081. $this->validate_options($options);
  1082. if(!$options){
  1083. $options = array();
  1084. }
  1085. //from bucket
  1086. $this->is_empty($from_bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1087. //to bucket
  1088. $this->is_empty($to_bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1089. //from object
  1090. $this->is_empty($from_object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1091. //to object
  1092. $this->is_empty($to_object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1093. $options[self::OSS_BUCKET] = $to_bucket;
  1094. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  1095. $options[self::OSS_OBJECT] = $to_object;
  1096. $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_COPY_SOURCE => '/'.$from_bucket.'/'.$from_object);
  1097. $response = $this->auth ( $options );
  1098. return $response;
  1099. }
  1100. /**
  1101. * 获得object的meta信息
  1102. * @param string $bucket (Required)
  1103. * @param string $object (Required)
  1104. * @param string $options (Optional)
  1105. * @author xiaobing.meng@alibaba-inc.com
  1106. * @since 2011-11-14
  1107. * @return ResponseCore
  1108. */
  1109. public function get_object_meta($bucket, $object, $options = NULL){
  1110. //options
  1111. $this->validate_options($options);
  1112. if(!$options){
  1113. $options = array();
  1114. }
  1115. //bucket
  1116. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1117. //object
  1118. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1119. $options[self::OSS_BUCKET] = $bucket;
  1120. $options[self::OSS_METHOD] = self::OSS_HTTP_HEAD;
  1121. $options[self::OSS_OBJECT] = $object;
  1122. $response = $this->auth ( $options );
  1123. return $response;
  1124. }
  1125. /**
  1126. * 删除object
  1127. * @param string $bucket(Required)
  1128. * @param string $object (Required)
  1129. * @param array $options (Optional)
  1130. * @author xiaobing.meng@alibaba-inc.com
  1131. * @since 2011-11-14
  1132. * @return ResponseCore
  1133. */
  1134. public function delete_object($bucket, $object, $options = NULL){
  1135. //options
  1136. $this->validate_options($options);
  1137. if(!$options){
  1138. $options = array();
  1139. }
  1140. //bucket
  1141. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1142. //object
  1143. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1144. $options[self::OSS_BUCKET] = $bucket;
  1145. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  1146. $options[self::OSS_OBJECT] = $object;
  1147. $response = $this->auth ( $options );
  1148. return $response;
  1149. }
  1150. /**
  1151. * 批量删除objects
  1152. * @param string $bucket(Required)
  1153. * @param array $objects (Required)
  1154. * @param array $options (Optional)
  1155. * @author xiaobing.meng@alibaba-inc.com
  1156. * @since 2012-03-09
  1157. * @return ResponseCore
  1158. */
  1159. public function delete_objects($bucket, $objects, $options = null){
  1160. //options
  1161. $this->validate_options($options);
  1162. if(!$options){
  1163. $options = array();
  1164. }
  1165. //bucket
  1166. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1167. //objects
  1168. if(!is_array($objects) || !$objects){
  1169. throw new OSS_Exception('The ' . __FUNCTION__ . ' method requires the "objects" option to be set as an array.');
  1170. }
  1171. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  1172. $options[self::OSS_BUCKET] = $bucket;
  1173. $options[self::OSS_OBJECT] = '/';
  1174. $options[self::OSS_SUB_RESOURCE] = 'delete';
  1175. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  1176. $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><Delete></Delete>');
  1177. // Quiet mode?
  1178. if (isset($options['quiet'])){
  1179. $quiet = 'false';
  1180. if (is_bool($options['quiet'])) { //Boolean
  1181. $quiet = $options['quiet'] ? 'true' : 'false';
  1182. }elseif (is_string($options['quiet'])){ // String
  1183. $quiet = ($options['quiet'] === 'true') ? 'true' : 'false';
  1184. }
  1185. $xml->addChild('Quiet', $quiet);
  1186. }
  1187. // Add the objects
  1188. foreach ($objects as $object){
  1189. $xobject = $xml->addChild('Object');
  1190. $object = $this->s_replace($object);
  1191. $xobject->addChild('Key', $object);
  1192. }
  1193. $options[self::OSS_CONTENT] = $xml->asXML();
  1194. return $this->auth($options);
  1195. }
  1196. /**
  1197. * 获得Object内容
  1198. * @param string $bucket(Required)
  1199. * @param string $object (Required)
  1200. * @param array $options (Optional)
  1201. * @author xiaobing.meng@alibaba-inc.com
  1202. * @since 2011-11-14
  1203. * @return ResponseCore
  1204. */
  1205. public function get_object($bucket, $object, $options = NULL){
  1206. //options
  1207. $this->validate_options($options);
  1208. if(!$options){
  1209. $options = array();
  1210. }
  1211. //bucket
  1212. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1213. //object
  1214. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1215. if(isset($options[self::OSS_FILE_DOWNLOAD]) && $this->chk_chinese($options[self::OSS_FILE_DOWNLOAD])){
  1216. $options[self::OSS_FILE_DOWNLOAD] = iconv('utf-8','gbk',$options[self::OSS_FILE_DOWNLOAD]);
  1217. }
  1218. $options[self::OSS_BUCKET] = $bucket;
  1219. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  1220. $options[self::OSS_OBJECT] = $object;
  1221. if(isset($options['lastmodified'])){
  1222. $options[self::OSS_HEADERS][self::OSS_IF_MODIFIED_SINCE] = $options['lastmodified'];
  1223. unset($options['lastmodified']);
  1224. }
  1225. if(isset($options['etag'])){
  1226. $options[self::OSS_HEADERS][self::OSS_IF_NONE_MATCH] = $options['etag'];
  1227. unset($options['etag']);
  1228. }
  1229. if(isset($options['range'])){
  1230. $options[self::OSS_HEADERS][self::OSS_RANGE] = 'bytes=' . $options['range'];
  1231. unset($options['range']);
  1232. }
  1233. return $this->auth ( $options );
  1234. }
  1235. /**
  1236. * 检测Object是否存在
  1237. * @param string $bucket(Required)
  1238. * @param string $object (Required)
  1239. * @param array $options (Optional)
  1240. * @author xiaobing.meng@alibaba-inc.com
  1241. * @since 2011-11-14
  1242. * @return boolean
  1243. */
  1244. public function is_object_exist($bucket, $object, $options = NULL){
  1245. //options
  1246. $this->validate_options($options);
  1247. if(!$options){
  1248. $options = array();
  1249. }
  1250. //bucket
  1251. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1252. //object
  1253. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1254. $options[self::OSS_BUCKET] = $bucket;
  1255. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  1256. $options[self::OSS_OBJECT] = $object;
  1257. $response = $this->get_object_meta($bucket, $object,$options);
  1258. return $response;
  1259. }
  1260. /*%******************************************************************************************************%*/
  1261. //Multi Part相关操作
  1262. /**
  1263. * 计算文件可以分成多少个part,以及每个part的长度以及起始位置
  1264. * 方法必须在 <upload_part()>中调用
  1265. *
  1266. * @param integer $filesize (Required) 文件大小
  1267. * @param integer $part_size (Required) part大小,默认5M
  1268. * @return array An array 包含 key-value 键值对. Key 为 `seekTo` 和 `length`.
  1269. */
  1270. public function get_multipart_counts($filesize, $part_size = 5242880 ){
  1271. $i = 0;
  1272. $sizecount = $filesize;
  1273. $values = array();
  1274. if((integer)$part_size <= 5242880){
  1275. $part_size = 5242880; //5M
  1276. }elseif ((integer)$part_size > 524288000){
  1277. $part_size = 524288000; //500M
  1278. }else{
  1279. $part_size = 52428800; //50M
  1280. }
  1281. while ($sizecount > 0)
  1282. {
  1283. $sizecount -= $part_size;
  1284. $values[] = array(
  1285. self::OSS_SEEK_TO => ($part_size * $i),
  1286. self::OSS_LENGTH => (($sizecount > 0) ? $part_size : ($sizecount + $part_size)),
  1287. );
  1288. $i++;
  1289. }
  1290. return $values;
  1291. }
  1292. /**
  1293. * 初始化multi-part upload,并且返回uploadId
  1294. * @param string $bucket (Required) Bucket名称
  1295. * @param string $object (Required) Object名称
  1296. * @param array $options (Optional) Key-Value数组,其中可以包括以下的key
  1297. * @return ResponseCore
  1298. */
  1299. public function initiate_multipart_upload($bucket, $object, $options = NULL){
  1300. //options
  1301. $this->validate_options($options);
  1302. if(!$options){
  1303. $options = array();
  1304. }
  1305. //bucket
  1306. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1307. //object
  1308. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1309. // 发送请求
  1310. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  1311. $options[self::OSS_BUCKET] = $bucket;
  1312. $options[self::OSS_OBJECT] = $object;
  1313. $options[self::OSS_SUB_RESOURCE] = 'uploads';
  1314. $options[self::OSS_CONTENT] = '';
  1315. //$options[self::OSS_CONTENT_LENGTH] = 0;
  1316. $options[self::OSS_HEADERS] = array(self::OSS_CONTENT_TYPE => 'application/octet-stream');
  1317. $response = $this->auth ( $options );
  1318. return $response;
  1319. }
  1320. /**
  1321. * 上传part
  1322. * @param string $bucket (Required) Bucket名称
  1323. * @param string $object (Required) Object名称
  1324. * @param string $upload_id (Required) uploadId
  1325. * @param array $options (Optional) Key-Value数组,其中可以包括以下的key
  1326. * @return ResponseCore
  1327. */
  1328. public function upload_part($bucket, $object, $upload_id, $options = null){
  1329. //options
  1330. $this->validate_options($options);
  1331. if(!$options){
  1332. $options = array();
  1333. }
  1334. //bucket
  1335. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1336. //object
  1337. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1338. if (!isset($options[self::OSS_FILE_UPLOAD]) || !isset($options['partNumber'])){
  1339. throw new OSS_Exception('The `fileUpload` and `partNumber` options are both required in ' . __FUNCTION__ . '().');
  1340. }
  1341. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  1342. $options[self::OSS_BUCKET] = $bucket;
  1343. $options[self::OSS_OBJECT] = $object;
  1344. $options[self::OSS_UPLOAD_ID] = $upload_id;
  1345. if(isset($options[self::OSS_LENGTH])){
  1346. $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
  1347. }
  1348. return $this->auth($options);
  1349. }
  1350. /**
  1351. * list part
  1352. * @param string $bucket (Required) Bucket名称
  1353. * @param string $object (Required) Object名称
  1354. * @param string $upload_id (Required) uploadId
  1355. * @param array $options (Optional) Key-Value数组,其中可以包括以下的key
  1356. * @return ResponseCore
  1357. */
  1358. public function list_parts($bucket, $object, $upload_id, $options = null){
  1359. //options
  1360. $this->validate_options($options);
  1361. if(!$options){
  1362. $options = array();
  1363. }
  1364. //bucket
  1365. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1366. //object
  1367. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1368. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  1369. $options[self::OSS_BUCKET] = $bucket;
  1370. $options[self::OSS_OBJECT] = $object;
  1371. $options[self::OSS_UPLOAD_ID] = $upload_id;
  1372. $options[self::OSS_QUERY_STRING] = array();
  1373. foreach (array('max-parts', 'part-number-marker') as $param){
  1374. if (isset($options[$param])){
  1375. $options[self::OSS_QUERY_STRING][$param] = $options[$param];
  1376. unset($options[$param]);
  1377. }
  1378. }
  1379. return $this->auth($options);
  1380. }
  1381. /**
  1382. * 中止上传mulit-part upload
  1383. * @param string $bucket (Required) Bucket名称
  1384. * @param string $object (Required) Object名称
  1385. * @param string $upload_id (Required) uploadId
  1386. * @param array $options (Optional) Key-Value数组,其中可以包括以下的key
  1387. * @return ResponseCore
  1388. */
  1389. public function abort_multipart_upload($bucket, $object, $upload_id, $options = NULL){
  1390. //options
  1391. $this->validate_options($options);
  1392. if(!$options){
  1393. $options = array();
  1394. }
  1395. //bucket
  1396. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1397. //object
  1398. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1399. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  1400. $options[self::OSS_BUCKET] = $bucket;
  1401. $options[self::OSS_OBJECT] = $object;
  1402. $options[self::OSS_UPLOAD_ID] = $upload_id;
  1403. return $this->auth($options);
  1404. }
  1405. /**
  1406. * 完成multi-part上传
  1407. * @param string $bucket (Required) Bucket名称
  1408. * @param string $object (Required) Object名称
  1409. * @param string $upload_id (Required) uploadId
  1410. * @param string $parts xml格式文件
  1411. * @param array $options (Optional) Key-Value数组,其中可以包括以下的key
  1412. * @return ResponseCore
  1413. */
  1414. public function complete_multipart_upload($bucket, $object, $upload_id, $parts, $options = NULL){
  1415. //options
  1416. $this->validate_options($options);
  1417. if(!$options){
  1418. $options = array();
  1419. }
  1420. //bucket
  1421. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1422. //object
  1423. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1424. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  1425. $options[self::OSS_BUCKET] = $bucket;
  1426. $options[self::OSS_OBJECT] = $object;
  1427. $options[self::OSS_UPLOAD_ID] = $upload_id;
  1428. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  1429. if(is_string($parts)){
  1430. $options[self::OSS_CONTENT] = $parts;
  1431. }else if($parts instanceof SimpleXMLElement){
  1432. $options[self::OSS_CONTENT] = $parts->asXML();
  1433. }else if((is_array($parts) || $parts instanceof ResponseCore)){
  1434. $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><CompleteMultipartUpload></CompleteMultipartUpload>');
  1435. if (is_array($parts)){
  1436. //生成关联的xml
  1437. foreach ($parts as $node){
  1438. $part = $xml->addChild('Part');
  1439. $part->addChild('PartNumber', $node['PartNumber']);
  1440. $part->addChild('ETag', $node['ETag']);
  1441. }
  1442. }elseif ($parts instanceof ResponseCore){
  1443. foreach ($parts->body->Part as $node){
  1444. $part = $xml->addChild('Part');
  1445. $part->addChild('PartNumber', (string) $node->PartNumber);
  1446. $part->addChild('ETag', (string) $node->ETag);
  1447. }
  1448. }
  1449. $options[self::OSS_CONTENT] = $xml->asXML();
  1450. }
  1451. return $this->auth($options);
  1452. }
  1453. /**
  1454. * 列出multipart上传
  1455. * @param string $bucket (Requeired) bucket
  1456. * @param array $options (Optional) 关联数组
  1457. * @author xiaobing.meng@alibaba-inc.com
  1458. * @since 2012-03-05
  1459. * @return ResponseCore
  1460. */
  1461. public function list_multipart_uploads($bucket, $options = null){
  1462. //options
  1463. $this->validate_options($options);
  1464. if(!$options){
  1465. $options = array();
  1466. }
  1467. //bucket
  1468. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1469. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  1470. $options[self::OSS_BUCKET] = $bucket;
  1471. $options[self::OSS_OBJECT] = '/';
  1472. $options[self::OSS_SUB_RESOURCE] = 'uploads';
  1473. foreach (array('key-marker', 'max-uploads', 'upload-id-marker') as $param){
  1474. if (isset($options[$param])){
  1475. $options[self::OSS_QUERY_STRING][$param] = $options[$param];
  1476. unset($options[$param]);
  1477. }
  1478. }
  1479. return $this->auth($options);
  1480. }
  1481. /**
  1482. * multipart上传统一封装,从初始化到完成multipart,以及出错后中止动作
  1483. * @param unknown_type $bucket
  1484. * @param unknown_type $object
  1485. * @param unknown_type $options
  1486. * @author xiaobing.meng@alibaba-inc.com
  1487. * @since 2012-03-05
  1488. * @return ResponseCore
  1489. */
  1490. public function create_mpu_object($bucket, $object, $options = null){
  1491. //options
  1492. $this->validate_options($options);
  1493. if(!$options){
  1494. $options = array();
  1495. }
  1496. //bucket
  1497. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1498. //object
  1499. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1500. if(isset($options[self::OSS_LENGTH])){
  1501. $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
  1502. unset($options[self::OSS_LENGTH]);
  1503. }
  1504. if(isset($options[self::OSS_FILE_UPLOAD])){
  1505. if($this->chk_chinese($options[self::OSS_FILE_UPLOAD])){
  1506. $options[self::OSS_FILE_UPLOAD] = mb_convert_encoding($options[self::OSS_FILE_UPLOAD],'UTF-8');
  1507. }
  1508. }
  1509. if(!isset($options[self::OSS_FILE_UPLOAD])){
  1510. throw new OSS_Exception('The `fileUpload` option is required in ' . __FUNCTION__ . '().');
  1511. }elseif (is_resource($options[self::OSS_FILE_UPLOAD])){
  1512. $upload_position = isset($options[self::OSS_SEEK_TO]) ? (integer) $options[self::OSS_SEEK_TO] : ftell($options[self::OSS_FILE_UPLOAD]);
  1513. $upload_filesize = isset($options[self::OSS_CONTENT_LENGTH]) ? (integer) $options[self::OSS_CONTENT_LENGTH] : null;
  1514. if (!isset($upload_filesize) && $upload_position !== false){
  1515. $stats = fstat($options[self::OSS_FILE_UPLOAD]);
  1516. if ($stats && $stats[self::OSS_SIZE] >= 0){
  1517. $upload_filesize = $stats[self::OSS_SIZE] - $upload_position;
  1518. }
  1519. }
  1520. }else{
  1521. $upload_position = isset($options[self::OSS_SEEK_TO]) ? (integer) $options[self::OSS_SEEK_TO] : 0;
  1522. if (isset($options[self::OSS_CONTENT_TYPE])){
  1523. $upload_filesize = (integer) $options[self::OSS_CONTENT_TYPE];
  1524. }
  1525. else{
  1526. $upload_filesize = filesize($options[self::OSS_FILE_UPLOAD]);
  1527. if ($upload_filesize !== false){
  1528. $upload_filesize -= $upload_position;
  1529. }
  1530. }
  1531. }
  1532. if ($upload_position === false || !isset($upload_filesize) || $upload_filesize === false || $upload_filesize < 0){
  1533. throw new OSS_Exception('The size of `fileUpload` cannot be determined in ' . __FUNCTION__ . '().');
  1534. }
  1535. // 处理partSize
  1536. if (isset($options[self::OSS_PART_SIZE])){
  1537. // 小于5M
  1538. if ((integer) $options[self::OSS_PART_SIZE] <= 5242880){
  1539. $options[self::OSS_PART_SIZE] = 5242880; // 5 MB
  1540. }
  1541. // 大于500M
  1542. elseif ((integer) $options[self::OSS_PART_SIZE] > 524288000){
  1543. $options[self::OSS_PART_SIZE] = 524288000; // 500 MB
  1544. }
  1545. }
  1546. else{
  1547. $options[self::OSS_PART_SIZE] = 52428800; // 50 MB
  1548. }
  1549. // 如果上传的文件小于partSize,则直接使用普通方式上传
  1550. if ($upload_filesize < $options[self::OSS_PART_SIZE] && !isset($options['uploadId'])){
  1551. return $this->upload_file_by_file($bucket, $object, $options[self::OSS_FILE_UPLOAD]);
  1552. }
  1553. // 初始化multipart
  1554. if (isset($options['uploadId'])){
  1555. $upload_id = $options['uploadId'];
  1556. }else{
  1557. //初始化
  1558. $upload = $this->initiate_multipart_upload($bucket, $object);
  1559. if (!$upload->isOK()){
  1560. throw new OSS_Exception('Init multi-part upload failed...');
  1561. }
  1562. $xml = new SimpleXmlIterator($upload->body);
  1563. $uploadId = (string)$xml->UploadId;
  1564. }
  1565. // 或的分片
  1566. $pieces = $this->get_multipart_counts($upload_filesize, (integer) $options[self::OSS_PART_SIZE]);
  1567. $response_upload_part = array();
  1568. foreach ($pieces as $i => $piece){
  1569. $response_upload_part[] = $this->upload_part($bucket, $object, $uploadId, array(
  1570. //'expect' => '100-continue',
  1571. self::OSS_FILE_UPLOAD => $options[self::OSS_FILE_UPLOAD],
  1572. 'partNumber' => ($i + 1),
  1573. self::OSS_SEEK_TO => $upload_position + (integer) $piece[self::OSS_SEEK_TO],
  1574. self::OSS_LENGTH => (integer) $piece[self::OSS_LENGTH],
  1575. ));
  1576. }
  1577. $upload_parts = array();
  1578. $upload_part_result = true;
  1579. foreach ($response_upload_part as $i=>$response){
  1580. $upload_part_result = $upload_part_result && $response->isOk();
  1581. }
  1582. if(!$upload_part_result){
  1583. throw new OSS_Exception('any part upload failed...,pls try again');
  1584. }
  1585. foreach ($response_upload_part as $i=>$response){
  1586. $upload_parts[] = array(
  1587. 'PartNumber' => ($i + 1),
  1588. 'ETag' => (string) $response->header['etag']
  1589. );
  1590. }
  1591. return $this->complete_multipart_upload($bucket, $object, $uploadId, $upload_parts);
  1592. }
  1593. /**
  1594. * 通过Multi-Part方式上传整个目录,其中的object默认为文件名
  1595. * @param string $bucket (Required)
  1596. * @param string $dir (Required) 必选
  1597. * @param boolean $recursive (Optional) 是否递归,如果为true,则递归读取所有目录,默认为不递归读取
  1598. * @param string $exclude 需要过滤的文件
  1599. * @param array $options (Optional) 关联数组
  1600. * @author xiaobing.meng@alibaba-inc.com
  1601. * @since 2012-03-05
  1602. * @return ResponseCore
  1603. */
  1604. public function create_mtu_object_by_dir($bucket, $dir, $recursive = false, $exclude = ".|..|.svn", $options = null){
  1605. //options
  1606. $this->validate_options($options);
  1607. //bucket
  1608. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1609. if($this->chk_chinese($dir)){
  1610. $dir = iconv('utf-8','gbk',$dir);
  1611. }
  1612. //判断是否目录
  1613. if(!is_dir($dir)){
  1614. throw new OSS_Exception($dir.' is not a directory...,pls check it');
  1615. }
  1616. $file_list_array = $this->read_dir($dir,$exclude,$recursive);
  1617. if(!$file_list_array){
  1618. throw new OSS_Exception($dir.' is empty...');
  1619. }
  1620. $index = 1;
  1621. foreach ($file_list_array as $item){
  1622. $options = array(
  1623. self::OSS_FILE_UPLOAD => $item['path'],
  1624. self::OSS_PART_SIZE => 5242880,
  1625. );
  1626. echo $index++.". ";
  1627. $response = $this->create_mpu_object($bucket, $item['file'],$options);
  1628. if($response->isOK()){
  1629. echo "Upload file {".$item['path']." } successful..\n";
  1630. }else{
  1631. echo "Upload file {".$item['path']." } failed..\n";
  1632. continue;
  1633. }
  1634. }
  1635. }
  1636. /**
  1637. * 通过multi-part方式上传目录(优化版)
  1638. * $options = array(
  1639. * 'bucket' => (Required)
  1640. * 'object' => (Optional)
  1641. * 'directory' => (Required)
  1642. * 'exclude' => (Optional)
  1643. * 'recursive' => (Optional)
  1644. * )
  1645. */
  1646. public function batch_upload_file($options = NULL){
  1647. if((NULL == $options) || !isset($options['bucket']) || empty($options['bucket']) || !isset($options['directory']) ||empty($options['directory']) ) {
  1648. throw new OSS_Exception('Bad Request',400);
  1649. }
  1650. $bucket = $options['bucket']; unset($options['bucket']);
  1651. $directory = $options['directory']; unset($options['directory']);
  1652. if($this->chk_chinese($directory)){
  1653. $directory = iconv('utf-8','gbk',$directory);
  1654. }
  1655. //判断是否目录
  1656. if(!is_dir($directory)){
  1657. throw new OSS_Exception($dir.' is not a directory...,pls check it');
  1658. }
  1659. $object = '';
  1660. if(isset($options['object'])){
  1661. $object = $options['object'];
  1662. unset($options['object']);
  1663. }
  1664. $exclude = '.|..|.svn';
  1665. if (isset($options['exclude']) && !empty($options['exclude'])){
  1666. $exclude = $options['exclude'];
  1667. unset($options['exclude']);
  1668. }
  1669. $recursive = false;
  1670. if(isset($options['recursive']) && !empty($options['recursive'])){
  1671. if(in_array($options['recursive'],array(true,false))){
  1672. $recursive = $options['recursive'];
  1673. }
  1674. unset($options['recursive']);
  1675. }
  1676. //read directory
  1677. $file_list_array = $this->read_dir($directory,$exclude,$recursive);
  1678. if(!$file_list_array){
  1679. throw new OSS_Exception($directory.' is empty...');
  1680. }
  1681. $index = 1;
  1682. foreach ($file_list_array as $item){
  1683. $options = array(
  1684. self::OSS_FILE_UPLOAD => $item['path'],
  1685. self::OSS_PART_SIZE => 5242880,
  1686. );
  1687. echo $index++.". ";
  1688. $response = $this->create_mpu_object($bucket, (!empty($object)?$object.'/':'').$item['file'],$options);
  1689. if($response->isOK()){
  1690. echo "Upload file {".$item['path']." } successful..\n";
  1691. }else{
  1692. echo "Upload file {".$item['path']." } failed..\n";
  1693. continue;
  1694. }
  1695. }
  1696. }
  1697. /*%******************************************************************************************************%*/
  1698. //Object Group相关操作
  1699. /**
  1700. * 创建Object Group
  1701. * @param string $object_group (Required) Object Group名称
  1702. * @param string $bucket (Required) Bucket名称
  1703. * @param array $object_arry (Required) object数组,所有的object必须在同一个bucket下
  1704. * 其中$object 数组的格式如下:
  1705. * $object = array(
  1706. * $object1,
  1707. * $object2,
  1708. * ...
  1709. * )
  1710. * @param array $options (Optional)
  1711. * @author xiaobing.meng@alibaba-inc.com
  1712. * @since 2011-11-14
  1713. * @return ResponseCore
  1714. */
  1715. public function create_object_group($bucket, $object_group, $object_arry, $options = NULL){
  1716. //options
  1717. $this->validate_options($options);
  1718. //bucket
  1719. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1720. //object group
  1721. $this->is_empty($object_group,OSS_OBJECT_GROUP_IS_NOT_ALLOWED_EMPTY);
  1722. $options[self::OSS_BUCKET] = $bucket;
  1723. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  1724. $options[self::OSS_OBJECT] = $object_group;
  1725. $options[self::OSS_CONTENT_TYPE] = 'txt/xml'; //重设Content-Type
  1726. $options[self::OSS_SUB_RESOURCE] = 'group'; //设置?group
  1727. $options[self::OSS_CONTENT] = $this->make_object_group_xml($bucket,$object_arry); //格式化xml
  1728. $response = $this->auth ( $options );
  1729. return $response;
  1730. }
  1731. /**
  1732. * 获取Object Group
  1733. * @param string $object_group (Required)
  1734. * @param string $bucket (Required)
  1735. * @param array $options (Optional)
  1736. * @author xiaobing.meng@alibaba-inc.com
  1737. * @since 2011-11-14
  1738. * @return ResponseCore
  1739. */
  1740. public function get_object_group($bucket, $object_group, $options = NULL){
  1741. //options
  1742. $this->validate_options($options);
  1743. //bucket
  1744. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1745. //object group
  1746. $this->is_empty($object_group,OSS_OBJECT_GROUP_IS_NOT_ALLOWED_EMPTY);
  1747. $options[self::OSS_BUCKET] = $bucket;
  1748. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  1749. $options[self::OSS_OBJECT] = $object_group;
  1750. //$options[self::OSS_OBJECT_GROUP] = true; //设置?group
  1751. //$options[self::OSS_CONTENT_TYPE] = 'txt/xml'; //重设Content-Type
  1752. $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_GROUP => self::OSS_OBJECT_GROUP); //header中的x-oss-file-group不能为空,否则返回值错误
  1753. $response = $this->auth ( $options );
  1754. return $response;
  1755. }
  1756. /**
  1757. * 获取Object Group 的Object List信息
  1758. * @param string $object_group (Required)
  1759. * @param string $bucket (Required)
  1760. * @param array $options (Optional)
  1761. * @author xiaobing.meng@alibaba-inc.com
  1762. * @since 2011-11-14
  1763. * @return ResponseCore
  1764. */
  1765. public function get_object_group_index($bucket, $object_group, $options = NULL){
  1766. //options
  1767. $this->validate_options($options);
  1768. //bucket
  1769. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1770. //object group
  1771. $this->is_empty($object_group,OSS_OBJECT_GROUP_IS_NOT_ALLOWED_EMPTY);
  1772. $options[self::OSS_BUCKET] = $bucket;
  1773. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  1774. $options[self::OSS_OBJECT] = $object_group;
  1775. $options[self::OSS_CONTENT_TYPE] = 'application/xml'; //重设Content-Type
  1776. //$options[self::OSS_OBJECT_GROUP] = true; //设置?group
  1777. $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_GROUP => self::OSS_OBJECT_GROUP);
  1778. $response = $this->auth ( $options );
  1779. return $response;
  1780. }
  1781. /**
  1782. * 获得object group的meta信息
  1783. * @param string $bucket (Required)
  1784. * @param string $object_group (Required)
  1785. * @param string $options (Optional)
  1786. * @author xiaobing.meng@alibaba-inc.com
  1787. * @since 2011-11-14
  1788. * @return ResponseCore
  1789. */
  1790. public function get_object_group_meta($bucket, $object_group, $options = NULL){
  1791. //options
  1792. $this->validate_options($options);
  1793. if(!$options){
  1794. $options = array();
  1795. }
  1796. //bucket
  1797. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1798. //object group
  1799. $this->is_empty($object_group,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1800. $options[self::OSS_BUCKET] = $bucket;
  1801. $options[self::OSS_METHOD] = self::OSS_HTTP_HEAD;
  1802. $options[self::OSS_OBJECT] = $object_group;
  1803. $options[self::OSS_CONTENT_TYPE] = 'application/xml'; //重设Content-Type
  1804. //$options[self::OSS_SUB_RESOURCE] = 'group'; //设置?group
  1805. $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_GROUP => self::OSS_OBJECT_GROUP);
  1806. $response = $this->auth ( $options );
  1807. return $response;
  1808. }
  1809. /**
  1810. * 删除Object Group
  1811. * @param string $bucket(Required)
  1812. * @param string $object_group (Required)
  1813. * @param array $options (Optional)
  1814. * @author xiaobing.meng@alibaba-inc.com
  1815. * @since 2011-11-14
  1816. * @return ResponseCore
  1817. */
  1818. public function delete_object_group($bucket, $object_group, $options = NULL){
  1819. //options
  1820. $this->validate_options($options);
  1821. if(!$options){
  1822. $options = array();
  1823. }
  1824. //bucket
  1825. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1826. //object group
  1827. $this->is_empty($object_group,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1828. $options[self::OSS_BUCKET] = $bucket;
  1829. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  1830. $options[self::OSS_OBJECT] = $object_group;
  1831. $response = $this->auth ( $options );
  1832. return $response;
  1833. }
  1834. /*%******************************************************************************************************%*/
  1835. //带签名的url相关
  1836. /**
  1837. * 获取带签名的url
  1838. * @param string $bucket (Required)
  1839. * @param string $object (Required)
  1840. * @param int $timeout (Optional)
  1841. * @param array $options (Optional)
  1842. * @author xiaobing.meng@alibaba-inc.com
  1843. * @since 2011-12-21
  1844. * @return string
  1845. */
  1846. public function get_sign_url($bucket, $object, $timeout = 60, $options = NULL){
  1847. //options
  1848. $this->validate_options($options);
  1849. if(!$options){
  1850. $options = array();
  1851. }
  1852. //bucket
  1853. $this->is_empty($bucket,OSS_BUCKET_IS_NOT_ALLOWED_EMPTY);
  1854. //object
  1855. $this->is_empty($object,OSS_OBJECT_IS_NOT_ALLOWED_EMPTY);
  1856. $options[self::OSS_BUCKET] = $bucket;
  1857. $options[self::OSS_OBJECT] = $object;
  1858. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  1859. $options[self::OSS_CONTENT_TYPE] = '';
  1860. $timeout = time() + $timeout;
  1861. $options[self::OSS_PREAUTH] = $timeout;
  1862. $options[self::OSS_DATE] = $timeout;
  1863. return $this->auth($options);
  1864. }
  1865. /*%******************************************************************************************************%*/
  1866. //日志相关
  1867. /**
  1868. * 记录日志
  1869. * @param string $msg (Required)
  1870. * @throws OSS_Exception
  1871. * @author xiaobing.meng@alibaba-inc.com
  1872. * @since 2011-12-27
  1873. * @return void
  1874. */
  1875. private function log($msg){
  1876. if(defined('ALI_LOG_PATH') ){
  1877. $log_path = ALI_LOG_PATH;
  1878. if(empty($log_path) || !file_exists($log_path)){
  1879. throw new OSS_Exception($log_path.OSS_LOG_PATH_NOT_EXIST);
  1880. }
  1881. }else{
  1882. $log_path = dirname(__FILE__).DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR;
  1883. }
  1884. //检测日志目录是否存在
  1885. if(!file_exists($log_path)){
  1886. throw new OSS_Exception(OSS_LOG_PATH_NOT_EXIST);
  1887. }
  1888. $log_name = $log_path.'oss_sdk_php_'.date('Y-m-d').'.log';
  1889. if(ALI_DISPLAY_LOG){
  1890. echo $msg."\n<br/>";
  1891. }
  1892. if(ALI_LOG){
  1893. if(!error_log(date('Y-m-d H:i:s')." : ".$msg."\n", 3,$log_name)){
  1894. throw new OSS_Exception(OSS_WRITE_LOG_TO_FILE_FAILED);
  1895. }
  1896. }
  1897. }
  1898. /*%******************************************************************************************************%*/
  1899. //工具类相关
  1900. /**
  1901. * 生成query params
  1902. * @param array $array 关联数组
  1903. * @author xiaobing.meng@alibaba-inc.com
  1904. * @since 2012-03-04
  1905. * @return string 返回诸如 key1=value1&key2=value2
  1906. */
  1907. public function to_query_string($options = array()){
  1908. $temp = array();
  1909. foreach ($options as $key => $value){
  1910. if (is_string($key) && !is_array($value)){
  1911. $temp[] = rawurlencode($key) . '=' . rawurlencode($value);
  1912. }
  1913. }
  1914. return implode('&', $temp);
  1915. }
  1916. /**
  1917. * 转化十六进制的数据为base64
  1918. *
  1919. * @param string $str (Required) 要转化的字符串
  1920. * @author xiaobing.meng@alibaba-inc.com
  1921. * @since 2012-03-20
  1922. * @return string Base64-encoded string.
  1923. */
  1924. private function hex_to_base64($str){
  1925. $result = '';
  1926. for ($i = 0; $i < strlen($str); $i += 2){
  1927. $result .= chr(hexdec(substr($str, $i, 2)));
  1928. }
  1929. return base64_encode($result);
  1930. }
  1931. private function s_replace($subject){
  1932. $search = array('<','>','&','\'','"');
  1933. $replace = array('&lt;','&gt;','&amp;','&apos;','&quot;');
  1934. return str_replace($search, $replace, $subject);
  1935. }
  1936. /**
  1937. * 替换控制字符,诸如&#26; 替换为%1A
  1938. * @param unknown $invalid_xml_chars
  1939. */
  1940. public function replace_invalid_xml_char($subject){
  1941. $search = array(
  1942. '&#01;','&#02;','&#03;','&#04;','&#05;','&#06;','&#07;','&#08;','&#09;','&#10;','&#11;','&#12;','&#13;',
  1943. '&#14;','&#15;','&#16;','&#17;','&#18;','&#19;','&#20;','&#21;','&#22;','&#23;','&#24;','&#25;','&#26;',
  1944. '&#27;','&#28;','&#29;','&#30;','&#31;','&#127;'
  1945. );
  1946. $replace = array(
  1947. '%01','%02','%03','%04','%05','%06','%07','%08','%09','%0A','%0B','%0C','%0D',
  1948. '%0E','%0F','%10','%11','%12','%13','%14','%15','%16','%17','%18','%19','%1A',
  1949. '%1B','%1C','%1D','%1E','%1F','%7F'
  1950. );
  1951. return str_replace($search, $replace, $subject);
  1952. }
  1953. /**
  1954. * 检测是否含有中文
  1955. * @param string $subject
  1956. * @author xiaobing.meng@alibaba-inc.com
  1957. * @since 2012-06-06
  1958. * @return boolean
  1959. */
  1960. private function chk_chinese($str){
  1961. return preg_match('/[\x80-\xff]./', $str);
  1962. }
  1963. /**
  1964. * 检测是否GB2312编码
  1965. * @param string $str
  1966. * @author xiaobing.meng@alibaba-inc.com
  1967. * @since 2012-03-20
  1968. * @return boolean false UTF-8编码 TRUE GB2312编码
  1969. */
  1970. function is_gb2312($str) {
  1971. for($i=0; $i<strlen($str); $i++) {
  1972. $v = ord( $str[$i] );
  1973. if( $v > 127) {
  1974. if( ($v >= 228) && ($v <= 233) ){
  1975. if( ($i+2) >= (strlen($str) - 1)) return true; // not enough characters
  1976. $v1 = ord( $str[$i+1] );
  1977. $v2 = ord( $str[$i+2] );
  1978. if( ($v1 >= 128) && ($v1 <=191) && ($v2 >=128) && ($v2 <= 191) )
  1979. return false; //UTF-8编码
  1980. else
  1981. return true; //GB编码
  1982. }
  1983. }
  1984. }
  1985. }
  1986. /**
  1987. * 检测是否GBK编码
  1988. * @param string $str
  1989. * @param boolean $gbk
  1990. * @author xiaobing.meng@alibaba-inc.com
  1991. * @since 2012-06-04
  1992. * @return boolean
  1993. */
  1994. private function check_char($str, $gbk = true){
  1995. for($i=0; $i<strlen($str); $i++) {
  1996. $v = ord( $str[$i] );
  1997. if( $v > 127){
  1998. if( ($v >= 228) && ($v <= 233) ){
  1999. if(($i+2)>= (strlen($str)-1)) return $gbk?true:FALSE; // not enough characters
  2000. $v1 = ord( $str[$i+1] ); $v2 = ord( $str[$i+2] );
  2001. if($gbk){
  2002. return (($v1 >= 128) && ($v1 <=191) && ($v2 >=128) && ($v2 <= 191))?FALSE:TRUE;//GBK
  2003. }else{
  2004. return (($v1 >= 128) && ($v1 <=191) && ($v2 >=128) && ($v2 <= 191))?TRUE:FALSE;
  2005. }
  2006. }
  2007. }
  2008. }
  2009. return $gbk?TRUE:FALSE;
  2010. }
  2011. /**
  2012. * 读取目录
  2013. * @param string $dir (Required) 目录名
  2014. * @param boolean $recursive (Optional) 是否递归,默认为false
  2015. * @author xiaobing.meng@alibaba-inc.com
  2016. * @since 2012-03-05
  2017. * @return array
  2018. */
  2019. private function read_dir($dir, $exclude = ".|..|.svn", $recursive = false){
  2020. static $file_list_array = array();
  2021. $exclude_array = explode("|", $exclude);
  2022. //读取目录
  2023. if($handle = opendir($dir)){
  2024. while ( false !== ($file = readdir($handle))){
  2025. if(!in_array(strtolower($file),$exclude_array)){
  2026. $new_file = $dir.'/'.$file;
  2027. if(is_dir($new_file) && $recursive){
  2028. $this->read_dir($new_file,$exclude,$recursive);
  2029. }else{
  2030. $file_list_array[] = array(
  2031. 'path' => $new_file,
  2032. 'file' => $file,
  2033. );
  2034. }
  2035. }
  2036. }
  2037. closedir($handle);
  2038. }
  2039. return $file_list_array;
  2040. }
  2041. /**
  2042. * 转化object数组为固定个xml格式
  2043. * @param string $bucket (Required)
  2044. * @param array $object_array (Required)
  2045. * @throws OSS_Exception
  2046. * @author xiaobing.meng@alibaba-inc.com
  2047. * @since 2011-12-27
  2048. * @return string
  2049. */
  2050. private function make_object_group_xml($bucket, $object_array){
  2051. $xml = '';
  2052. $xml .= '<CreateFileGroup>';
  2053. if($object_array){
  2054. if(count($object_array) > self::OSS_MAX_OBJECT_GROUP_VALUE){
  2055. throw new OSS_Exception(OSS_OBJECT_GROUP_TOO_MANY_OBJECT, '-401');
  2056. }
  2057. $index = 1;
  2058. foreach ($object_array as $key=>$value){
  2059. $object_meta = (array)$this->get_object_meta($bucket, $value);
  2060. if(isset($object_meta) && isset($object_meta['status']) && isset($object_meta['header']) && isset($object_meta['header']['etag']) && $object_meta['status'] == 200){
  2061. $xml .= '<Part>';
  2062. $xml .= '<PartNumber>'.intval($index).'</PartNumber>';
  2063. $xml .= '<PartName>'.$value.'</PartName>';
  2064. $xml .= '<ETag>'.$object_meta['header']['etag'].'</ETag>';
  2065. $xml .= '</Part>';
  2066. $index++;
  2067. }
  2068. }
  2069. }else{
  2070. throw new OSS_Exception(OSS_OBJECT_ARRAY_IS_EMPTY, '-400');
  2071. }
  2072. $xml .= '</CreateFileGroup>';
  2073. return $xml;
  2074. }
  2075. /**
  2076. * 检验bucket名称是否合法
  2077. * bucket的命名规范:
  2078. * 1. 只能包括小写字母,数字
  2079. * 2. 必须以小写字母或者数字开头
  2080. * 3. 长度必须在3-63字节之间
  2081. * @param string $bucket (Required)
  2082. * @author xiaobing.meng@alibaba-inc.com
  2083. * @since 2011-12-27
  2084. * @return boolean
  2085. */
  2086. private function validate_bucket($bucket){
  2087. $pattern = '/^[a-z0-9][a-z0-9-]{2,62}$/';
  2088. if (! preg_match ( $pattern, $bucket )) {
  2089. return false;
  2090. }
  2091. return true;
  2092. }
  2093. /**
  2094. * 检验object名称是否合法
  2095. * object命名规范:
  2096. * 1. 规则长度必须在1-1023字节之间
  2097. * 2. 使用UTF-8编码
  2098. * @param string $object (Required)
  2099. * @author xiaobing.meng@alibaba-inc.com
  2100. * @since 2011-12-27
  2101. * @return boolean
  2102. */
  2103. private function validate_object($object){
  2104. $pattern = '/^.{1,1023}$/';
  2105. if (empty ( $object ) || ! preg_match ( $pattern, $object )) {
  2106. return false;
  2107. }
  2108. return true;
  2109. }
  2110. /**
  2111. * 检验$options
  2112. * @param array $options (Optional)
  2113. * @throws OSS_Exception
  2114. * @author xiaobing.meng@alibaba-inc.com
  2115. * @since 2011-12-27
  2116. * @return boolean
  2117. */
  2118. private function validate_options($options){
  2119. //$options
  2120. if ($options != NULL && ! is_array ( $options )) {
  2121. throw new OSS_Exception ($options.':'.OSS_OPTIONS_MUST_BE_ARRAY);
  2122. }
  2123. }
  2124. /**
  2125. * 检测上传文件的内容
  2126. * @param array $options (Optional)
  2127. * @throws OSS_Exception
  2128. * @author xiaobing.meng@alibaba-inc.com
  2129. * @since 2011-12-27
  2130. * @return string
  2131. */
  2132. private function validate_content($options){
  2133. if(isset($options[self::OSS_CONTENT])){
  2134. if($options[self::OSS_CONTENT] == '' || !is_string($options[self::OSS_CONTENT])){
  2135. throw new OSS_Exception(OSS_INVALID_HTTP_BODY_CONTENT,'-600');
  2136. }
  2137. }else{
  2138. throw new OSS_Exception(OSS_NOT_SET_HTTP_CONTENT, '-601');
  2139. }
  2140. }
  2141. /**
  2142. * 验证文件长度
  2143. * @param array $options (Optional)
  2144. * @author xiaobing.meng@alibaba-inc.com
  2145. * @since 2011-12-27
  2146. * @return void
  2147. */
  2148. private function validate_content_length($options){
  2149. if(isset($options[self::OSS_LENGTH]) && is_numeric($options[self::OSS_LENGTH])){
  2150. if( ! $options[self::OSS_LENGTH] > 0){
  2151. throw new OSS_Exception(OSS_CONTENT_LENGTH_MUST_MORE_THAN_ZERO, '-602');
  2152. }
  2153. }else{
  2154. throw new OSS_Exception(OSS_INVALID_CONTENT_LENGTH, '-602');
  2155. }
  2156. }
  2157. /**
  2158. * 校验BUCKET/OBJECT/OBJECT GROUP是否为空
  2159. * @param string $name (Required)
  2160. * @param string $errMsg (Required)
  2161. * @throws OSS_Exception
  2162. * @author xiaobing.meng@alibaba-inc.com
  2163. * @since 2011-12-27
  2164. * @return void
  2165. */
  2166. private function is_empty($name,$errMsg){
  2167. if(empty($name)){
  2168. throw new OSS_Exception($errMsg);
  2169. }
  2170. }
  2171. /**
  2172. * 设置http header
  2173. * @param string $key (Required)
  2174. * @param string $value (Required)
  2175. * @param array $options (Required)
  2176. * @throws OSS_Exception
  2177. * @author xiaobing.meng@alibaba-inc.com
  2178. * @return void
  2179. */
  2180. private static function set_options_header($key, $value, &$options) {
  2181. if (isset ( $options [self::OSS_HEADERS] )) {
  2182. if (! is_array ( $options [self::OSS_HEADERS] )) {
  2183. throw new OSS_Exception(OSS_INVALID_OPTION_HEADERS, '-600');
  2184. }
  2185. } else {
  2186. $options [self::OSS_HEADERS] = array ();
  2187. }
  2188. $options [self::OSS_HEADERS] [$key] = $value;
  2189. }
  2190. }