Cosapi.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  1. <?php
  2. namespace Qcloud_cos;
  3. date_default_timezone_set('PRC');
  4. class Cosapi
  5. {
  6. //计算sign签名的时间参数
  7. const EXPIRED_SECONDS = 180;
  8. //512K
  9. const SLICE_SIZE_512K = 524288;
  10. //1M
  11. const SLICE_SIZE_1M = 1048576;
  12. //2M
  13. const SLICE_SIZE_2M = 2097152;
  14. //3M
  15. const SLICE_SIZE_3M = 3145728;
  16. //20M 大于20M的文件需要进行分片传输
  17. const MAX_UNSLICE_FILE_SIZE = 20971520;
  18. //失败尝试次数
  19. const MAX_RETRY_TIMES = 3;
  20. //返回的错误码
  21. const COSAPI_PARAMS_ERROR = -1;
  22. const COSAPI_NETWORK_ERROR = -2;
  23. //HTTP请求超时时间
  24. private static $timeout = 60;
  25. /*
  26. * 设置HTTP请求超时时间
  27. * @param int $timeout 超时时长
  28. */
  29. public static function setTimeout($timeout = 60) {
  30. if (!is_int($timeout) || $timeout < 0) {
  31. return false;
  32. }
  33. self::$timeout = $timeout;
  34. return true;
  35. }
  36. /**
  37. * 上传文件,自动判断文件大小,如果小于20M则使用普通文件上传,大于20M则使用分片上传
  38. * @param string $bucketName bucket名称
  39. * @param string $srcPath 本地文件路径
  40. * @param string $dstPath 上传的文件路径
  41. * @param string $bizAttr 文件属性
  42. * @param string $slicesize 分片大小(512k,1m,2m,3m),默认:1m
  43. * @param string $insertOnly 同名文件是否覆盖
  44. * @return [type] [description]
  45. */
  46. public static function upload($bucketName, $srcPath, $dstPath,
  47. $bizAttr = null, $slicesize = null, $insertOnly = null)
  48. {
  49. if (!file_exists($srcPath)) {
  50. return array(
  51. 'code' => self::COSAPI_PARAMS_ERROR,
  52. 'message' => 'file '.$srcPath.' not exists',
  53. 'data' => array());
  54. }
  55. //文件大于20M则使用分片传输
  56. if (filesize($srcPath) < self::MAX_UNSLICE_FILE_SIZE ) {
  57. return self::uploadfile($bucketName, $srcPath, $dstPath, $bizAttr, $insertOnly);
  58. } else {
  59. $sliceSize = self::getSliceSize($slicesize);
  60. return self::upload_slice($bucketName, $srcPath, $dstPath, $bizAttr, $sliceSize, $insertOnly);
  61. }
  62. }
  63. /*
  64. * 创建目录
  65. * @param string $bucketName bucket名称
  66. * @param string $path 目录路径
  67. * @param string $bizAttr 目录属性
  68. */
  69. public static function createFolder($bucketName, $path, $bizAttr = null) {
  70. $path = self::normalizerPath($path, True);
  71. $path = self::cosUrlEncode($path);
  72. $expired = time() + self::EXPIRED_SECONDS;
  73. $url = self::generateResUrl($bucketName, $path);
  74. $sign = Auth::appSign($expired, $bucketName);
  75. $data = array(
  76. 'op' => 'create',
  77. 'biz_attr' => (isset($bizAttr) ? $bizAttr : ''),
  78. );
  79. $data = json_encode($data);
  80. $req = array(
  81. 'url' => $url,
  82. 'method' => 'post',
  83. 'timeout' => self::$timeout,
  84. 'data' => $data,
  85. 'header' => array(
  86. 'Authorization:'.$sign,
  87. 'Content-Type: application/json',
  88. ),
  89. );
  90. return self::sendRequest($req);
  91. }
  92. /*
  93. * 目录列表
  94. * @param string $bucketName bucket名称
  95. * @param string $path 目录路径,sdk会补齐末尾的 '/'
  96. * @param int $num 拉取的总数
  97. * @param string $pattern eListBoth,ListDirOnly,eListFileOnly 默认both
  98. * @param int $order 默认正序(=0), 填1为反序,
  99. * @param string $offset 透传字段,用于翻页,前端不需理解,需要往前/往后翻页则透传回来
  100. */
  101. public static function listFolder(
  102. $bucketName, $path, $num = 20,
  103. $pattern = 'eListBoth', $order = 0,
  104. $context = null) {
  105. $path = self::normalizerPath($path,True);
  106. return self::listBase($bucketName, $path, $num,
  107. $pattern, $order, $context);
  108. }
  109. /*
  110. * 目录列表(前缀搜索)
  111. * @param string $bucketName bucket名称
  112. * @param string $prefix 列出含此前缀的所有文件
  113. * @param int $num 拉取的总数
  114. * @param string $pattern eListBoth(默认),ListDirOnly,eListFileOnly
  115. * @param int $order 默认正序(=0), 填1为反序,
  116. * @param string $offset 透传字段,用于翻页,前端不需理解,需要往前/往后翻页则透传回来
  117. */
  118. public static function prefixSearch(
  119. $bucketName, $prefix, $num = 20,
  120. $pattern = 'eListBoth', $order = 0,
  121. $context = null) {
  122. $path = self::normalizerPath($prefix);
  123. return self::listBase($bucketName, $prefix, $num,
  124. $pattern, $order, $context);
  125. }
  126. /*
  127. * 目录更新
  128. * @param string $bucketName bucket名称
  129. * @param string $path 文件夹路径,SDK会补齐末尾的 '/'
  130. * @param string $bizAttr 目录属性
  131. */
  132. public static function updateFolder($bucketName, $path, $bizAttr = null) {
  133. $path = self::normalizerPath($path, True);
  134. return self::updateBase($bucketName, $path, $bizAttr);
  135. }
  136. /*
  137. * 查询目录信息
  138. * @param string $bucketName bucket名称
  139. * @param string $path 目录路径
  140. */
  141. public static function statFolder($bucketName, $path) {
  142. $path = self::normalizerPath($path, True);
  143. return self::statBase($bucketName, $path);
  144. }
  145. /*
  146. * 删除目录
  147. * @param string $bucketName bucket名称
  148. * @param string $path 目录路径
  149. * 注意不能删除bucket下根目录/
  150. */
  151. public static function delFolder($bucketName, $path) {
  152. $path = self::normalizerPath($path, True);
  153. return self::delBase($bucketName, $path);
  154. }
  155. /*
  156. * 更新文件
  157. * @param string $bucketName bucket名称
  158. * @param string $path 文件路径
  159. * @param string $authority: eInvalid(继承Bucket的读写权限)/eWRPrivate(私有读写)/eWPrivateRPublic(公有读私有写)
  160. * @param array $customer_headers_array 携带的用户自定义头域,包括
  161. * 'Cache-Control' => '*'
  162. * 'Content-Type' => '*'
  163. * 'Content-Disposition' => '*'
  164. * 'Content-Language' => '*'
  165. * 'x-cos-meta-自定义内容' => '*'
  166. */
  167. public static function update($bucketName, $path,
  168. $bizAttr = null, $authority=null,$customer_headers_array=null) {
  169. $path = self::normalizerPath($path);
  170. return self::updateBase($bucketName, $path, $bizAttr, $authority, $customer_headers_array);
  171. }
  172. /*
  173. * 移动(重命名)文件
  174. * @param string $bucketName bucket名称
  175. * @param string $srcPath 源文件路径
  176. * @param string $dstPath 目的文件名(可以是单独文件名也可以是带目录的文件名)
  177. * @param string $toOverWrite 是否覆盖(当目的文件名已经存在同名文件时是否覆盖)
  178. */
  179. public static function move($bucketName, $srcPath, $dstPath, $toOverWrite = 0)
  180. {
  181. $srcPath = self::cosUrlEncode($srcPath);
  182. $url = self::generateResUrl($bucketName,$srcPath);
  183. $sign = Auth::appSign_once($srcPath, $bucketName);
  184. $expired = time() + self::EXPIRED_SECONDS;
  185. $data = array(
  186. 'op' => 'move',
  187. 'dest_fileid' => $dstPath,
  188. 'to_over_write' => $toOverWrite,
  189. );
  190. $data = json_encode($data);
  191. $req = array(
  192. 'url' => $url,
  193. 'method' => 'post',
  194. 'timeout' => self::$timeout,
  195. 'data' => $data,
  196. 'header' => array(
  197. 'Authorization: '.$sign,
  198. 'Content-Type: application/json',
  199. ),
  200. );
  201. return self::sendRequest($req);
  202. }
  203. /*
  204. * 查询文件信息
  205. * @param string $bucketName bucket名称
  206. * @param string $path 文件路径
  207. */
  208. public static function stat($bucketName, $path) {
  209. $path = self::normalizerPath($path);
  210. return self::statBase($bucketName, $path);
  211. }
  212. /*
  213. * 删除文件
  214. * @param string $bucketName
  215. * @param string $path 文件路径
  216. */
  217. public static function delFile($bucketName, $path) {
  218. $path = self::normalizerPath($path);
  219. return self::delBase($bucketName, $path);
  220. }
  221. /**
  222. * 内部方法, 上传文件
  223. * @param string $bucketName bucket名称
  224. * @param string $srcPath 本地文件路径
  225. * @param string $dstPath 上传的文件路径
  226. * @param string $bizAttr 文件属性
  227. * @param int $insertOnly 是否覆盖同名文件:0 覆盖,1:不覆盖
  228. * @return [type] [description]
  229. */
  230. private static function uploadfile($bucketName, $srcPath, $dstPath, $bizAttr = null, $insertOnly = null)
  231. {
  232. $srcPath = realpath($srcPath);
  233. $dstPath = self::cosUrlEncode($dstPath);
  234. if (filesize($srcPath) >= self::MAX_UNSLICE_FILE_SIZE )
  235. {
  236. return array(
  237. 'code' => self::COSAPI_PARAMS_ERROR,
  238. 'message' => 'file '.$srcPath.' larger then 20M, please use upload_slice interface',
  239. 'data' => array());
  240. }
  241. $expired = time() + self::EXPIRED_SECONDS;
  242. $url = self::generateResUrl($bucketName, $dstPath);
  243. $sign = Auth::appSign($expired, $bucketName);
  244. $sha1 = hash_file('sha1', $srcPath);
  245. $data = array(
  246. 'op' => 'upload',
  247. 'sha' => $sha1,
  248. 'biz_attr' => (isset($bizAttr) ? $bizAttr : ''),
  249. );
  250. if (function_exists('curl_file_create')) {
  251. $data['filecontent'] = curl_file_create($srcPath);
  252. } else {
  253. $data['filecontent'] = '@'.$srcPath;
  254. }
  255. if (isset($insertOnly) && strlen($insertOnly) > 0)
  256. $data['insertOnly'] = (($insertOnly == 0 || $insertOnly == '0' ) ? 0 : 1);
  257. $req = array(
  258. 'url' => $url,
  259. 'method' => 'post',
  260. 'timeout' => self::$timeout,
  261. 'data' => $data,
  262. 'header' => array(
  263. 'Authorization:'.$sign,
  264. ),
  265. );
  266. return self::sendRequest($req);
  267. }
  268. /**
  269. * 内部方法,上传文件
  270. * @param string $bucketName bucket名称
  271. * @param string $srcPath 本地文件路径
  272. * @param string $dstPath 上传的文件路径
  273. * @param string $bizAttr 文件属性
  274. * @param string $sliceSize 分片大小
  275. * @param int $insertOnly 是否覆盖同名文件:0 覆盖,1:不覆盖
  276. * @return [type] [description]
  277. */
  278. private static function upload_slice(
  279. $bucketName, $srcPath, $dstPath,
  280. $bizAttr = null, $sliceSize = null, $insertOnly=null) {
  281. $srcPath = realpath($srcPath);
  282. $fileSize = filesize($srcPath);
  283. $dstPath = self::cosUrlEncode($dstPath);
  284. $expired = time() + self::EXPIRED_SECONDS;
  285. $url = self::generateResUrl($bucketName, $dstPath);
  286. $sign = Auth::appSign($expired, $bucketName);
  287. $sha1 = hash_file('sha1', $srcPath);
  288. $ret = self::upload_prepare(
  289. $fileSize, $sha1, $sliceSize,
  290. $sign, $url, $bizAttr, $insertOnly);
  291. if($ret['code'] != 0) {
  292. return $ret;
  293. }
  294. if(isset($ret['data'])
  295. && isset($ret['data']['url'])) {
  296. //秒传命中,直接返回了url
  297. return $ret;
  298. }
  299. $sliceSize = $ret['data']['slice_size'];
  300. if ($sliceSize > self::SLICE_SIZE_3M ||
  301. $sliceSize <= 0) {
  302. $ret['code'] = self::COSAPI_PARAMS_ERROR;
  303. $ret['message'] = 'illegal slice size';
  304. return $ret;
  305. }
  306. $session = $ret['data']['session'];
  307. $offset = $ret['data']['offset'];
  308. $sliceCnt = ceil($fileSize / $sliceSize);
  309. // expired seconds for one slice mutiply by slice count
  310. // will be the expired seconds for whole file
  311. $expired = time() + (self::EXPIRED_SECONDS * $sliceCnt);
  312. $sign = Auth::appSign($expired, $bucketName);
  313. $ret = self::upload_data(
  314. $fileSize, $sha1, $sliceSize,
  315. $sign, $url, $srcPath,
  316. $offset, $session);
  317. return $ret;
  318. }
  319. /**
  320. * 第一个分片控制消息
  321. * @param string $fileSize 文件大小
  322. * @param string $sha1 文件sha值
  323. * @param string $sliceSize 分片大小
  324. * @param string $sign 签名
  325. * @param string $url URL
  326. * @param string $bizAttr 文件属性
  327. * @param string $insertOnly 同名文件是否覆盖
  328. * @return [type]
  329. */
  330. private static function upload_prepare(
  331. $fileSize, $sha1, $sliceSize,
  332. $sign, $url, $bizAttr = null, $insertOnly = null) {
  333. $data = array(
  334. 'op' => 'upload_slice',
  335. 'filesize' => $fileSize,
  336. 'sha' => $sha1,
  337. );
  338. if (isset($bizAttr) && strlen($bizAttr))
  339. $data['biz_attr'] = $bizAttr;
  340. if (isset($insertOnly))
  341. $data['insertOnly'] = (($insertOnly == 0) ? 0 : 1);
  342. if ($sliceSize <= self::SLICE_SIZE_3M) {
  343. $data['slice_size'] = $sliceSize;
  344. } else {
  345. $data['slice_size'] = self::SLICE_SIZE_3M;
  346. }
  347. $req = array(
  348. 'url' => $url,
  349. 'method' => 'post',
  350. 'timeout' => self::$timeout,
  351. 'data' => $data,
  352. 'header' => array(
  353. 'Authorization:'.$sign,
  354. ),
  355. );
  356. $ret = self::sendRequest($req);
  357. return $ret;
  358. }
  359. /**
  360. * 分片上传
  361. * @param int $fileSize 文件大小
  362. * @param string $sha1 文件sha值
  363. * @param int $sliceSize 文件分片大小
  364. * @param string $sign 签名
  365. * @param string $url url
  366. * @param string $srcPath 源文件路径
  367. * @param int $offset 文件偏移offset
  368. * @param string $session session
  369. * @return [type] array
  370. */
  371. private static function upload_data(
  372. $fileSize, $sha1, $sliceSize,
  373. $sign, $url, $srcPath,
  374. $offset, $session) {
  375. while ($fileSize > $offset) {
  376. $filecontent = file_get_contents(
  377. $srcPath, false, null,
  378. $offset, $sliceSize);
  379. if ($filecontent === false) {
  380. return array(
  381. 'code' => self::COSAPI_PARAMS_ERROR,
  382. 'message' => 'read file '.$srcPath.' error',
  383. 'data' => array(),
  384. );
  385. }
  386. $boundary = '---------------------------' . substr(md5(mt_rand()), 0, 10);
  387. $data = self::generateSliceBody(
  388. $filecontent, $offset, $sha1,
  389. $session, basename($srcPath), $boundary);
  390. $req = array(
  391. 'url' => $url,
  392. 'method' => 'post',
  393. 'timeout' => self::$timeout,
  394. 'data' => $data,
  395. 'header' => array(
  396. 'Authorization:'.$sign,
  397. 'Content-Type: multipart/form-data; boundary=' . $boundary,
  398. ),
  399. );
  400. $retry_times = 0;
  401. do {
  402. $ret = self::sendRequest($req);
  403. if ($ret['code'] == 0) {
  404. break;
  405. }
  406. $retry_times++;
  407. } while($retry_times < self::MAX_RETRY_TIMES);
  408. if($ret['code'] != 0) {
  409. return $ret;
  410. }
  411. if ($ret['data']['session']) {
  412. $session = $ret['data']['session'];
  413. }
  414. $offset += $sliceSize;
  415. }
  416. return $ret;
  417. }
  418. /**
  419. * 构造分片body体
  420. * @param string $fileContent 文件内容
  421. * @param string $offset 文件偏移
  422. * @param string $sha 文件sha值
  423. * @param string $session session
  424. * @param string $fileName 文件名
  425. * @param string $boundary 分隔符
  426. * @return [type]
  427. */
  428. private static function generateSliceBody(
  429. $fileContent, $offset, $sha,
  430. $session, $fileName, $boundary) {
  431. $formdata = '';
  432. $formdata .= '--' . $boundary . "\r\n";
  433. $formdata .= "content-disposition: form-data; name=\"op\"\r\n\r\nupload_slice\r\n";
  434. $formdata .= '--' . $boundary . "\r\n";
  435. $formdata .= "content-disposition: form-data; name=\"offset\"\r\n\r\n" . $offset. "\r\n";
  436. $formdata .= '--' . $boundary . "\r\n";
  437. $formdata .= "content-disposition: form-data; name=\"session\"\r\n\r\n" . $session . "\r\n";
  438. $formdata .= '--' . $boundary . "\r\n";
  439. $formdata .= "content-disposition: form-data; name=\"fileContent\"; filename=\"" . $fileName . "\"\r\n";
  440. $formdata .= "content-type: application/octet-stream\r\n\r\n";
  441. $data = $formdata . $fileContent . "\r\n--" . $boundary . "--\r\n";
  442. return $data;
  443. }
  444. /*
  445. * 内部公共函数
  446. * @param string $bucketName bucket名称
  447. * @param string $path 文件夹路径
  448. * @param int $num 拉取的总数
  449. * @param string $pattern eListBoth(默认),ListDirOnly,eListFileOnly
  450. * @param int $order 默认正序(=0), 填1为反序,
  451. * @param string $context 在翻页查询时候用到
  452. */
  453. private static function listBase(
  454. $bucketName, $path, $num = 20,
  455. $pattern = 'eListBoth', $order = 0, $context = null) {
  456. $path = self::cosUrlEncode($path);
  457. $expired = time() + self::EXPIRED_SECONDS;
  458. $url = self::generateResUrl($bucketName, $path);
  459. $sign = Auth::appSign($expired, $bucketName);
  460. $data = array(
  461. 'op' => 'list',
  462. );
  463. if (self::isPatternValid($pattern) == false)
  464. {
  465. return array(
  466. 'code' => self::COSAPI_PARAMS_ERROR,
  467. 'message' => 'parameter pattern invalid',
  468. );
  469. }
  470. $data['pattern'] = $pattern;
  471. if ($order != 0 && $order != 1)
  472. {
  473. return array(
  474. 'code' => self::COSAPI_PARAMS_ERROR,
  475. 'message' => 'parameter order invalid',
  476. );
  477. }
  478. $data['order'] = $order;
  479. if ($num < 0 || $num > 199)
  480. {
  481. return array(
  482. 'code' => self::COSAPI_PARAMS_ERROR,
  483. 'message' => 'parameter num invalid, num need less then 200',
  484. );
  485. }
  486. $data['num'] = $num;
  487. if (isset($context))
  488. {
  489. $data['context'] = $context;
  490. }
  491. $url = $url . '?' . http_build_query($data);
  492. $req = array(
  493. 'url' => $url,
  494. 'method' => 'get',
  495. 'timeout' => self::$timeout,
  496. 'header' => array(
  497. 'Authorization:'.$sign,
  498. ),
  499. );
  500. return self::sendRequest($req);
  501. }
  502. /*
  503. * 内部公共方法(更新文件和更新文件夹)
  504. * @param string $bucketName bucket名称
  505. * @param string $path 路径
  506. * @param string $bizAttr 文件/目录属性
  507. * @param string $authority: eInvalid/eWRPrivate(私有)/eWPrivateRPublic(公有读写)
  508. * @param array $customer_headers_array 携带的用户自定义头域,包括
  509. * 'Cache-Control' => '*'
  510. * 'Content-Type' => '*'
  511. * 'Content-Disposition' => '*'
  512. * 'Content-Language' => '*'
  513. * 'x-cos-meta-自定义内容' => '*'
  514. */
  515. private static function updateBase($bucketName, $path,
  516. $bizAttr = null, $authority = null, $custom_headers_array = null) {
  517. $path = self::cosUrlEncode($path);
  518. $expired = time() + self::EXPIRED_SECONDS;
  519. $url = self::generateResUrl($bucketName, $path);
  520. $sign = Auth::appSign_once(
  521. $path, $bucketName);
  522. $data = array(
  523. 'op' => 'update',
  524. );
  525. $flag = 0;
  526. if (isset($bizAttr))
  527. {
  528. $data['biz_attr'] = $bizAttr;
  529. $flag = $flag | 0x01;
  530. }
  531. if (isset($authority) && strlen($authority) > 0)
  532. {
  533. if(self::isAuthorityValid($authority) == false)
  534. {
  535. return array(
  536. 'code' => self::COSAPI_PARAMS_ERROR,
  537. 'message' => 'parameter authority invalid',
  538. );
  539. }
  540. $data['authority'] = $authority;
  541. $flag = $flag | 0x80;
  542. }
  543. if (isset($custom_headers_array))
  544. {
  545. $data['custom_headers'] = array();
  546. self::add_customer_header($data['custom_headers'], $custom_headers_array);
  547. $flag = $flag | 0x40;
  548. }
  549. if ($flag != 0 && $flag != 1)
  550. {
  551. $data['flag'] = $flag;
  552. }
  553. $data = json_encode($data);
  554. $req = array(
  555. 'url' => $url,
  556. 'method' => 'post',
  557. 'timeout' => self::$timeout,
  558. 'data' => $data,
  559. 'header' => array(
  560. 'Authorization:'.$sign,
  561. 'Content-Type: application/json',
  562. ),
  563. );
  564. return self::sendRequest($req);
  565. }
  566. /*
  567. * 内部方法
  568. * @param string $bucketName bucket名称
  569. * @param string $path 文件/目录路径
  570. */
  571. private static function statBase($bucketName, $path) {
  572. $path = self::cosUrlEncode($path);
  573. $expired = time() + self::EXPIRED_SECONDS;
  574. $url = self::generateResUrl($bucketName, $path);
  575. $sign = Auth::appSign($expired, $bucketName);
  576. $data = array(
  577. 'op' => 'stat',
  578. );
  579. $url = $url . '?' . http_build_query($data);
  580. $req = array(
  581. 'url' => $url,
  582. 'method' => 'get',
  583. 'timeout' => self::$timeout,
  584. 'header' => array(
  585. 'Authorization:'.$sign,
  586. ),
  587. );
  588. return self::sendRequest($req);
  589. }
  590. /*
  591. * 内部私有方法
  592. * @param string $bucketName bucket名称
  593. * @param string $path 文件/目录路径路径
  594. */
  595. private static function delBase($bucketName, $path) {
  596. if ($path == "/") {
  597. return array(
  598. 'code' => self::COSAPI_PARAMS_ERROR,
  599. 'message' => 'can not delete bucket using api! go to http://console.qcloud.com/cos to operate bucket',
  600. );
  601. }
  602. $path = self::cosUrlEncode($path);
  603. $expired = time() + self::EXPIRED_SECONDS;
  604. $url = self::generateResUrl($bucketName, $path);
  605. $sign = Auth::appSign_once(
  606. $path, $bucketName);
  607. $data = array(
  608. 'op' => 'delete',
  609. );
  610. $data = json_encode($data);
  611. $req = array(
  612. 'url' => $url,
  613. 'method' => 'post',
  614. 'timeout' => self::$timeout,
  615. 'data' => $data,
  616. 'header' => array(
  617. 'Authorization:'.$sign,
  618. 'Content-Type: application/json',
  619. ),
  620. );
  621. return self::sendRequest($req);
  622. }
  623. /*
  624. * 内部公共方法, 路径编码
  625. * @param string $path 待编码路径
  626. */
  627. private static function cosUrlEncode($path) {
  628. return str_replace('%2F', '/', rawurlencode($path));
  629. }
  630. /*
  631. * 内部公共方法, 构造URL
  632. * @param string $bucketName
  633. * @param string $dstPath
  634. */
  635. private static function generateResUrl($bucketName, $dstPath) {
  636. return Conf::API_COSAPI_END_POINT . Conf::APPID . '/' . $bucketName . $dstPath;
  637. }
  638. /*
  639. * 内部公共方法, 发送消息
  640. * @param string $req
  641. */
  642. private static function sendRequest($req) {
  643. $rsp = Http::send($req);
  644. $info = Http::info();
  645. $ret = json_decode($rsp, true);
  646. if ($ret) {
  647. if (0 === $ret['code']) {
  648. return $ret;
  649. } else {
  650. return array(
  651. 'code' => $ret['code'],
  652. 'message' => $ret['message'],
  653. 'data' => array()
  654. );
  655. }
  656. } else {
  657. return array(
  658. 'code' => self::COSAPI_NETWORK_ERROR,
  659. 'message' => $rsp,
  660. 'data' => array()
  661. );
  662. }
  663. }
  664. /**
  665. * 设置分片大小
  666. * @param string $sliceSize
  667. * @return [type] int
  668. */
  669. private static function getSliceSize($sliceSize)
  670. {
  671. $size = self::SLICE_SIZE_1M;
  672. if (!isset($sliceSize))
  673. {
  674. return $size;
  675. }
  676. if ($sliceSize <= self::SLICE_SIZE_512K)
  677. {
  678. $size = self::SLICE_SIZE_512K;
  679. }
  680. else if ($sliceSize <= self::SLICE_SIZE_1M)
  681. {
  682. $size = self::SLICE_SIZE_1M;
  683. }
  684. else if ($sliceSize <= self::SLICE_SIZE_2M)
  685. {
  686. $size = self::SLICE_SIZE_2M;
  687. }
  688. else
  689. {
  690. $size = self::SLICE_SIZE_3M;
  691. }
  692. return $size;
  693. }
  694. /*
  695. * 内部方法, 规整文件路径
  696. * @param string $path 文件路径
  697. * @param string $isfolder 是否为文件夹
  698. */
  699. private static function normalizerPath($path, $isfolder = False) {
  700. if (preg_match('/^\//', $path) == 0) {
  701. $path = '/' . $path;
  702. }
  703. if ($isfolder == True)
  704. {
  705. if (preg_match('/\/$/', $path) == 0) {
  706. $path = $path . '/';
  707. }
  708. }
  709. return $path;
  710. }
  711. /**
  712. * 判断authority值是否正确
  713. * @param string $authority
  714. * @return [type] bool
  715. */
  716. private static function isAuthorityValid($authority)
  717. {
  718. if ($authority == 'eInvalid'
  719. || $authority == 'eWRPrivate'
  720. || $authority == 'eWPrivateRPublic')
  721. {
  722. return true;
  723. }
  724. return false;
  725. }
  726. /**
  727. * 判断pattern值是否正确
  728. * @param string $authority
  729. * @return [type] bool
  730. */
  731. private static function isPatternValid($pattern)
  732. {
  733. if ($pattern == 'eListBoth'
  734. || $pattern == 'eListDirOnly'
  735. || $pattern == 'eListFileOnly')
  736. {
  737. return true;
  738. }
  739. return false;
  740. }
  741. /**
  742. * 判断是否符合自定义属性
  743. * @param string $key
  744. * @return [type] bool
  745. */
  746. private static function isCustomer_header($key)
  747. {
  748. if ($key == 'Cache-Control'
  749. || $key == 'Content-Type'
  750. || $key == 'Content-Disposition'
  751. || $key == 'Content-Language'
  752. || substr($key,0,strlen('x-cos-meta-')) == 'x-cos-meta-')
  753. {
  754. return true;
  755. }
  756. return false;
  757. }
  758. /**
  759. * 增加自定义属性到data中
  760. * @param array $data
  761. * @param array $customer_headers_array
  762. * @return [type] void
  763. */
  764. private static function add_customer_header(&$data, &$customer_headers_array)
  765. {
  766. if (count($customer_headers_array) < 1) return;
  767. foreach($customer_headers_array as $key=>$value)
  768. {
  769. if(self::isCustomer_header($key))
  770. {
  771. $data[$key] = $value;
  772. }
  773. }
  774. }
  775. }