sdk.class.php 76 KB

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