cosapi.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. <?php
  2. namespace qcloudcos;
  3. require_once(__DIR__ . DIRECTORY_SEPARATOR . 'error_code.php');
  4. date_default_timezone_set('PRC');
  5. class Cosapi {
  6. //计算sign签名的时间参数
  7. const EXPIRED_SECONDS = 180;
  8. //1M
  9. const SLICE_SIZE_1M = 1048576;
  10. //20M 大于20M的文件需要进行分片传输
  11. const MAX_UNSLICE_FILE_SIZE = 20971520;
  12. //失败尝试次数
  13. const MAX_RETRY_TIMES = 3;
  14. //HTTP请求超时时间
  15. private static $timeout = 60;
  16. private static $region = 'gz'; // default region is guangzhou
  17. /**
  18. * 设置HTTP请求超时时间
  19. * @param int $timeout 超时时长
  20. */
  21. public static function setTimeout($timeout = 60) {
  22. if (!is_int($timeout) || $timeout < 0) {
  23. return false;
  24. }
  25. self::$timeout = $timeout;
  26. return true;
  27. }
  28. public static function setRegion($region) {
  29. self::$region = $region;
  30. }
  31. /**
  32. * 上传文件,自动判断文件大小,如果小于20M则使用普通文件上传,大于20M则使用分片上传
  33. * @param string $bucket bucket名称
  34. * @param string $srcPath 本地文件路径
  35. * @param string $dstPath 上传的文件路径
  36. * @param string $bizAttr 文件属性
  37. * @param string $slicesize 分片大小(512k,1m,2m,3m),默认:1m
  38. * @param string $insertOnly 同名文件是否覆盖
  39. * @return [type] [description]
  40. */
  41. public static function upload(
  42. $bucket, $srcPath, $dstPath, $bizAttr=null, $sliceSize=null, $insertOnly=null) {
  43. if (!file_exists($srcPath)) {
  44. return array(
  45. 'code' => COSAPI_PARAMS_ERROR,
  46. 'message' => 'file ' . $srcPath .' not exists',
  47. 'data' => array()
  48. );
  49. }
  50. $dstPath = self::normalizerPath($dstPath, false);
  51. //文件大于20M则使用分片传输
  52. if (filesize($srcPath) < self::MAX_UNSLICE_FILE_SIZE ) {
  53. return self::uploadFile($bucket, $srcPath, $dstPath, $bizAttr, $insertOnly);
  54. } else {
  55. $sliceSize = self::getSliceSize($sliceSize);
  56. return self::uploadBySlicing($bucket, $srcPath, $dstPath, $bizAttr, $sliceSize, $insertOnly);
  57. }
  58. }
  59. /*
  60. * 创建目录
  61. * @param string $bucket bucket名称
  62. * @param string $folder 目录路径
  63. * @param string $bizAttr 目录属性
  64. */
  65. public static function createFolder($bucket, $folder, $bizAttr = null) {
  66. if (!self::isValidPath($folder)) {
  67. return array(
  68. 'code' => COSAPI_PARAMS_ERROR,
  69. 'message' => 'folder ' . $path . ' is not a valid folder name',
  70. 'data' => array()
  71. );
  72. }
  73. $folder = self::normalizerPath($folder, True);
  74. $folder = self::cosUrlEncode($folder);
  75. $expired = time() + self::EXPIRED_SECONDS;
  76. $url = self::generateResUrl($bucket, $folder);
  77. $signature = Auth::createReusableSignature($expired, $bucket);
  78. $data = array(
  79. 'op' => 'create',
  80. 'biz_attr' => (isset($bizAttr) ? $bizAttr : ''),
  81. );
  82. $data = json_encode($data);
  83. $req = array(
  84. 'url' => $url,
  85. 'method' => 'post',
  86. 'timeout' => self::$timeout,
  87. 'data' => $data,
  88. 'header' => array(
  89. 'Authorization: ' . $signature,
  90. 'Content-Type: application/json',
  91. ),
  92. );
  93. return self::sendRequest($req);
  94. }
  95. /*
  96. * 目录列表
  97. * @param string $bucket bucket名称
  98. * @param string $path 目录路径,sdk会补齐末尾的 '/'
  99. * @param int $num 拉取的总数
  100. * @param string $pattern eListBoth,ListDirOnly,eListFileOnly 默认both
  101. * @param int $order 默认正序(=0), 填1为反序,
  102. * @param string $offset 透传字段,用于翻页,前端不需理解,需要往前/往后翻页则透传回来
  103. */
  104. public static function listFolder(
  105. $bucket, $folder, $num = 20,
  106. $pattern = 'eListBoth', $order = 0,
  107. $context = null) {
  108. $folder = self::normalizerPath($folder, True);
  109. return self::listBase($bucket, $folder, $num, $pattern, $order, $context);
  110. }
  111. /*
  112. * 目录列表(前缀搜索)
  113. * @param string $bucket bucket名称
  114. * @param string $prefix 列出含此前缀的所有文件
  115. * @param int $num 拉取的总数
  116. * @param string $pattern eListBoth(默认),ListDirOnly,eListFileOnly
  117. * @param int $order 默认正序(=0), 填1为反序,
  118. * @param string $offset 透传字段,用于翻页,前端不需理解,需要往前/往后翻页则透传回来
  119. */
  120. public static function prefixSearch(
  121. $bucket, $prefix, $num = 20,
  122. $pattern = 'eListBoth', $order = 0,
  123. $context = null) {
  124. $path = self::normalizerPath($prefix);
  125. return self::listBase($bucket, $prefix, $num, $pattern, $order, $context);
  126. }
  127. /*
  128. * 目录更新
  129. * @param string $bucket bucket名称
  130. * @param string $folder 文件夹路径,SDK会补齐末尾的 '/'
  131. * @param string $bizAttr 目录属性
  132. */
  133. public static function updateFolder($bucket, $folder, $bizAttr = null) {
  134. $folder = self::normalizerPath($folder, True);
  135. return self::updateBase($bucket, $folder, $bizAttr);
  136. }
  137. /*
  138. * 查询目录信息
  139. * @param string $bucket bucket名称
  140. * @param string $folder 目录路径
  141. */
  142. public static function statFolder($bucket, $folder) {
  143. $folder = self::normalizerPath($folder, True);
  144. return self::statBase($bucket, $folder);
  145. }
  146. /*
  147. * 删除目录
  148. * @param string $bucket bucket名称
  149. * @param string $folder 目录路径
  150. * 注意不能删除bucket下根目录/
  151. */
  152. public static function delFolder($bucket, $folder) {
  153. if (empty($bucket) || empty($folder)) {
  154. return array(
  155. 'code' => COSAPI_PARAMS_ERROR,
  156. 'message' => 'bucket or path is empty');
  157. }
  158. $folder = self::normalizerPath($folder, True);
  159. return self::delBase($bucket, $folder);
  160. }
  161. /*
  162. * 更新文件
  163. * @param string $bucket bucket名称
  164. * @param string $path 文件路径
  165. * @param string $authority: eInvalid(继承Bucket的读写权限)/eWRPrivate(私有读写)/eWPrivateRPublic(公有读私有写)
  166. * @param array $customer_headers_array 携带的用户自定义头域,包括
  167. * 'Cache-Control' => '*'
  168. * 'Content-Type' => '*'
  169. * 'Content-Disposition' => '*'
  170. * 'Content-Language' => '*'
  171. * 'x-cos-meta-自定义内容' => '*'
  172. */
  173. public static function update($bucket, $path,
  174. $bizAttr = null, $authority=null,$customer_headers_array=null) {
  175. $path = self::normalizerPath($path);
  176. return self::updateBase($bucket, $path, $bizAttr, $authority, $customer_headers_array);
  177. }
  178. /*
  179. * 查询文件信息
  180. * @param string $bucket bucket名称
  181. * @param string $path 文件路径
  182. */
  183. public static function stat($bucket, $path) {
  184. $path = self::normalizerPath($path);
  185. return self::statBase($bucket, $path);
  186. }
  187. /*
  188. * 删除文件
  189. * @param string $bucket
  190. * @param string $path 文件路径
  191. */
  192. public static function delFile($bucket, $path) {
  193. if (empty($bucket) || empty($path)) {
  194. return array(
  195. 'code' => COSAPI_PARAMS_ERROR,
  196. 'message' => 'path is empty');
  197. }
  198. $path = self::normalizerPath($path);
  199. return self::delBase($bucket, $path);
  200. }
  201. /**
  202. * 内部方法, 上传文件
  203. * @param string $bucket bucket名称
  204. * @param string $srcPath 本地文件路径
  205. * @param string $dstPath 上传的文件路径
  206. * @param string $bizAttr 文件属性
  207. * @param int $insertOnly 是否覆盖同名文件:0 覆盖,1:不覆盖
  208. * @return [type] [description]
  209. */
  210. private static function uploadFile($bucket, $srcPath, $dstPath, $bizAttr = null, $insertOnly = null) {
  211. $srcPath = realpath($srcPath);
  212. $dstPath = self::cosUrlEncode($dstPath);
  213. if (filesize($srcPath) >= self::MAX_UNSLICE_FILE_SIZE ) {
  214. return array(
  215. 'code' => COSAPI_PARAMS_ERROR,
  216. 'message' => 'file '.$srcPath.' larger then 20M, please use uploadBySlicing interface',
  217. 'data' => array()
  218. );
  219. }
  220. $expired = time() + self::EXPIRED_SECONDS;
  221. $url = self::generateResUrl($bucket, $dstPath);
  222. $signature = Auth::createReusableSignature($expired, $bucket);
  223. $fileSha = hash_file('sha1', $srcPath);
  224. $data = array(
  225. 'op' => 'upload',
  226. 'sha' => $fileSha,
  227. 'biz_attr' => (isset($bizAttr) ? $bizAttr : ''),
  228. );
  229. $data['filecontent'] = file_get_contents($srcPath);
  230. if (isset($insertOnly) && strlen($insertOnly) > 0) {
  231. $data['insertOnly'] = (($insertOnly == 0 || $insertOnly == '0' ) ? 0 : 1);
  232. }
  233. $req = array(
  234. 'url' => $url,
  235. 'method' => 'post',
  236. 'timeout' => self::$timeout,
  237. 'data' => $data,
  238. 'header' => array(
  239. 'Authorization: ' . $signature,
  240. ),
  241. );
  242. return self::sendRequest($req);
  243. }
  244. /**
  245. * 内部方法,上传文件
  246. * @param string $bucket bucket名称
  247. * @param string $srcPath 本地文件路径
  248. * @param string $dstPath 上传的文件路径
  249. * @param string $bizAttr 文件属性
  250. * @param string $sliceSize 分片大小
  251. * @param int $insertOnly 是否覆盖同名文件:0 覆盖,1:不覆盖
  252. * @return [type] [description]
  253. */
  254. private static function uploadBySlicing(
  255. $bucket, $srcFpath, $dstFpath, $bizAttr=null, $sliceSize=null, $insertOnly=null) {
  256. $srcFpath = realpath($srcFpath);
  257. $fileSize = filesize($srcFpath);
  258. $dstFpath = self::cosUrlEncode($dstFpath);
  259. $url = self::generateResUrl($bucket, $dstFpath);
  260. $sliceCount = ceil($fileSize / $sliceSize);
  261. // expiration seconds for one slice mutiply by slice count
  262. // will be the expired seconds for whole file
  263. $expiration = time() + (self::EXPIRED_SECONDS * $sliceCount);
  264. if ($expiration >= (time() + 10 * 24 * 60 * 60)) {
  265. $expiration = time() + 10 * 24 * 60 * 60;
  266. }
  267. $signature = Auth::createReusableSignature($expiration, $bucket);
  268. $sliceUploading = new SliceUploading(self::$timeout * 1000, self::MAX_RETRY_TIMES);
  269. for ($tryCount = 0; $tryCount < self::MAX_RETRY_TIMES; ++$tryCount) {
  270. if ($sliceUploading->initUploading(
  271. $signature,
  272. $srcFpath,
  273. $url,
  274. $fileSize, $sliceSize, $bizAttr, $insertOnly)) {
  275. break;
  276. }
  277. $errorCode = $sliceUploading->getLastErrorCode();
  278. if ($errorCode === -4019) {
  279. // Delete broken file and retry again on _ERROR_FILE_NOT_FINISH_UPLOAD error.
  280. Cosapi::delFile($bucket, $dstFpath);
  281. continue;
  282. }
  283. if ($tryCount === self::MAX_RETRY_TIMES - 1) {
  284. return array(
  285. 'code' => $sliceUploading->getLastErrorCode(),
  286. 'message' => $sliceUploading->getLastErrorMessage(),
  287. 'request_id' => $sliceUploading->getRequestId(),
  288. );
  289. }
  290. }
  291. if (!$sliceUploading->performUploading()) {
  292. return array(
  293. 'code' => $sliceUploading->getLastErrorCode(),
  294. 'message' => $sliceUploading->getLastErrorMessage(),
  295. 'request_id' => $sliceUploading->getRequestId(),
  296. );
  297. }
  298. if (!$sliceUploading->finishUploading()) {
  299. return array(
  300. 'code' => $sliceUploading->getLastErrorCode(),
  301. 'message' => $sliceUploading->getLastErrorMessage(),
  302. 'request_id' => $sliceUploading->getRequestId(),
  303. );
  304. }
  305. return array(
  306. 'code' => 0,
  307. 'message' => 'success',
  308. 'request_id' => $sliceUploading->getRequestId(),
  309. 'data' => array(
  310. 'access_url' => $sliceUploading->getAccessUrl(),
  311. 'resource_path' => $sliceUploading->getResourcePath(),
  312. 'source_url' => $sliceUploading->getSourceUrl(),
  313. ),
  314. );
  315. }
  316. /*
  317. * 内部公共函数
  318. * @param string $bucket bucket名称
  319. * @param string $path 文件夹路径
  320. * @param int $num 拉取的总数
  321. * @param string $pattern eListBoth(默认),ListDirOnly,eListFileOnly
  322. * @param int $order 默认正序(=0), 填1为反序,
  323. * @param string $context 在翻页查询时候用到
  324. */
  325. private static function listBase(
  326. $bucket, $path, $num = 20, $pattern = 'eListBoth', $order = 0, $context = null) {
  327. $path = self::cosUrlEncode($path);
  328. $expired = time() + self::EXPIRED_SECONDS;
  329. $url = self::generateResUrl($bucket, $path);
  330. $signature = Auth::createReusableSignature($expired, $bucket);
  331. $data = array(
  332. 'op' => 'list',
  333. );
  334. if (self::isPatternValid($pattern) == false) {
  335. return array(
  336. 'code' => COSAPI_PARAMS_ERROR,
  337. 'message' => 'parameter pattern invalid',
  338. );
  339. }
  340. $data['pattern'] = $pattern;
  341. if ($order != 0 && $order != 1) {
  342. return array(
  343. 'code' => COSAPI_PARAMS_ERROR,
  344. 'message' => 'parameter order invalid',
  345. );
  346. }
  347. $data['order'] = $order;
  348. if ($num < 0 || $num > 199) {
  349. return array(
  350. 'code' => COSAPI_PARAMS_ERROR,
  351. 'message' => 'parameter num invalid, num need less then 200',
  352. );
  353. }
  354. $data['num'] = $num;
  355. if (isset($context)) {
  356. $data['context'] = $context;
  357. }
  358. $url = $url . '?' . http_build_query($data);
  359. $req = array(
  360. 'url' => $url,
  361. 'method' => 'get',
  362. 'timeout' => self::$timeout,
  363. 'header' => array(
  364. 'Authorization: ' . $signature,
  365. ),
  366. );
  367. return self::sendRequest($req);
  368. }
  369. /*
  370. * 内部公共方法(更新文件和更新文件夹)
  371. * @param string $bucket bucket名称
  372. * @param string $path 路径
  373. * @param string $bizAttr 文件/目录属性
  374. * @param string $authority: eInvalid/eWRPrivate(私有)/eWPrivateRPublic(公有读写)
  375. * @param array $customer_headers_array 携带的用户自定义头域,包括
  376. * 'Cache-Control' => '*'
  377. * 'Content-Type' => '*'
  378. * 'Content-Disposition' => '*'
  379. * 'Content-Language' => '*'
  380. * 'x-cos-meta-自定义内容' => '*'
  381. */
  382. private static function updateBase(
  383. $bucket, $path, $bizAttr = null, $authority = null, $custom_headers_array = null) {
  384. $path = self::cosUrlEncode($path);
  385. $expired = time() + self::EXPIRED_SECONDS;
  386. $url = self::generateResUrl($bucket, $path);
  387. $signature = Auth::createNonreusableSignature($bucket, $path);
  388. $data = array('op' => 'update');
  389. if (isset($bizAttr)) {
  390. $data['biz_attr'] = $bizAttr;
  391. }
  392. if (isset($authority) && strlen($authority) > 0) {
  393. if(self::isAuthorityValid($authority) == false) {
  394. return array(
  395. 'code' => COSAPI_PARAMS_ERROR,
  396. 'message' => 'parameter authority invalid');
  397. }
  398. $data['authority'] = $authority;
  399. }
  400. if (isset($custom_headers_array)) {
  401. $data['custom_headers'] = array();
  402. self::add_customer_header($data['custom_headers'], $custom_headers_array);
  403. }
  404. $data = json_encode($data);
  405. $req = array(
  406. 'url' => $url,
  407. 'method' => 'post',
  408. 'timeout' => self::$timeout,
  409. 'data' => $data,
  410. 'header' => array(
  411. 'Authorization: ' . $signature,
  412. 'Content-Type: application/json',
  413. ),
  414. );
  415. return self::sendRequest($req);
  416. }
  417. /*
  418. * 内部方法
  419. * @param string $bucket bucket名称
  420. * @param string $path 文件/目录路径
  421. */
  422. private static function statBase($bucket, $path) {
  423. $path = self::cosUrlEncode($path);
  424. $expired = time() + self::EXPIRED_SECONDS;
  425. $url = self::generateResUrl($bucket, $path);
  426. $signature = Auth::createReusableSignature($expired, $bucket);
  427. $data = array('op' => 'stat');
  428. $url = $url . '?' . http_build_query($data);
  429. $req = array(
  430. 'url' => $url,
  431. 'method' => 'get',
  432. 'timeout' => self::$timeout,
  433. 'header' => array(
  434. 'Authorization: ' . $signature,
  435. ),
  436. );
  437. return self::sendRequest($req);
  438. }
  439. /*
  440. * 内部私有方法
  441. * @param string $bucket bucket名称
  442. * @param string $path 文件/目录路径路径
  443. */
  444. private static function delBase($bucket, $path) {
  445. if ($path == "/") {
  446. return array(
  447. 'code' => COSAPI_PARAMS_ERROR,
  448. 'message' => 'can not delete bucket using api! go to ' .
  449. 'http://console.qcloud.com/cos to operate bucket');
  450. }
  451. $path = self::cosUrlEncode($path);
  452. $expired = time() + self::EXPIRED_SECONDS;
  453. $url = self::generateResUrl($bucket, $path);
  454. $signature = Auth::createNonreusableSignature($bucket, $path);
  455. $data = array('op' => 'delete');
  456. $data = json_encode($data);
  457. $req = array(
  458. 'url' => $url,
  459. 'method' => 'post',
  460. 'timeout' => self::$timeout,
  461. 'data' => $data,
  462. 'header' => array(
  463. 'Authorization: ' . $signature,
  464. 'Content-Type: application/json',
  465. ),
  466. );
  467. return self::sendRequest($req);
  468. }
  469. /*
  470. * 内部公共方法, 路径编码
  471. * @param string $path 待编码路径
  472. */
  473. private static function cosUrlEncode($path) {
  474. return str_replace('%2F', '/', rawurlencode($path));
  475. }
  476. /*
  477. * 内部公共方法, 构造URL
  478. * @param string $bucket
  479. * @param string $dstPath
  480. */
  481. private static function generateResUrl($bucket, $dstPath) {
  482. global $_W;
  483. $endPoint = Conf::API_COSAPI_END_POINT;
  484. $endPoint = str_replace('region', self::$region, $endPoint);
  485. return $endPoint . (!empty($_W['setting']['remote']['cos']['appid']) ? $_W['setting']['remote']['cos']['appid'] : Conf::APP_ID) . '/' . $bucket . $dstPath;
  486. }
  487. /*
  488. * 内部公共方法, 发送消息
  489. * @param string $req
  490. */
  491. private static function sendRequest($req) {
  492. $rsp = HttpClient::sendRequest($req);
  493. if ($rsp === false) {
  494. return array(
  495. 'code' => COSAPI_NETWORK_ERROR,
  496. 'message' => 'network error',
  497. );
  498. }
  499. $info = HttpClient::info();
  500. $ret = json_decode($rsp, true);
  501. if ($ret === NULL) {
  502. return array(
  503. 'code' => COSAPI_NETWORK_ERROR,
  504. 'message' => $rsp,
  505. 'data' => array()
  506. );
  507. }
  508. return $ret;
  509. }
  510. /**
  511. * Get slice size.
  512. */
  513. private static function getSliceSize($sliceSize) {
  514. // Fix slice size to 1MB.
  515. return self::SLICE_SIZE_1M;
  516. }
  517. /*
  518. * 内部方法, 规整文件路径
  519. * @param string $path 文件路径
  520. * @param string $isfolder 是否为文件夹
  521. */
  522. private static function normalizerPath($path, $isfolder = False) {
  523. if (preg_match('/^\//', $path) == 0) {
  524. $path = '/' . $path;
  525. }
  526. if ($isfolder == True) {
  527. if (preg_match('/\/$/', $path) == 0) {
  528. $path = $path . '/';
  529. }
  530. }
  531. // Remove unnecessary slashes.
  532. $path = preg_replace('#/+#', '/', $path);
  533. return $path;
  534. }
  535. /**
  536. * 判断authority值是否正确
  537. * @param string $authority
  538. * @return [type] bool
  539. */
  540. private static function isAuthorityValid($authority) {
  541. if ($authority == 'eInvalid' || $authority == 'eWRPrivate' || $authority == 'eWPrivateRPublic') {
  542. return true;
  543. }
  544. return false;
  545. }
  546. /**
  547. * 判断pattern值是否正确
  548. * @param string $authority
  549. * @return [type] bool
  550. */
  551. private static function isPatternValid($pattern) {
  552. if ($pattern == 'eListBoth' || $pattern == 'eListDirOnly' || $pattern == 'eListFileOnly') {
  553. return true;
  554. }
  555. return false;
  556. }
  557. /**
  558. * 判断是否符合自定义属性
  559. * @param string $key
  560. * @return [type] bool
  561. */
  562. private static function isCustomer_header($key) {
  563. if ($key == 'Cache-Control' || $key == 'Content-Type' ||
  564. $key == 'Content-Disposition' || $key == 'Content-Language' ||
  565. $key == 'Content-Encoding' ||
  566. substr($key,0,strlen('x-cos-meta-')) == 'x-cos-meta-') {
  567. return true;
  568. }
  569. return false;
  570. }
  571. /**
  572. * 增加自定义属性到data中
  573. * @param array $data
  574. * @param array $customer_headers_array
  575. * @return [type] void
  576. */
  577. private static function add_customer_header(&$data, &$customer_headers_array) {
  578. if (count($customer_headers_array) < 1) {
  579. return;
  580. }
  581. foreach($customer_headers_array as $key=>$value) {
  582. if(self::isCustomer_header($key)) {
  583. $data[$key] = $value;
  584. }
  585. }
  586. }
  587. // Check |$path| is a valid file path.
  588. // Return true on success, otherwise return false.
  589. private static function isValidPath($path) {
  590. if (strpos($path, '?') !== false) {
  591. return false;
  592. }
  593. if (strpos($path, '*') !== false) {
  594. return false;
  595. }
  596. if (strpos($path, ':') !== false) {
  597. return false;
  598. }
  599. if (strpos($path, '|') !== false) {
  600. return false;
  601. }
  602. if (strpos($path, '\\') !== false) {
  603. return false;
  604. }
  605. if (strpos($path, '<') !== false) {
  606. return false;
  607. }
  608. if (strpos($path, '>') !== false) {
  609. return false;
  610. }
  611. if (strpos($path, '"') !== false) {
  612. return false;
  613. }
  614. return true;
  615. }
  616. /**
  617. * Copy a file.
  618. * @param $bucket bucket name.
  619. * @param $srcFpath source file path.
  620. * @param $dstFpath destination file path.
  621. * @param $overwrite if the destination location is occupied, overwrite it or not?
  622. * @return array|mixed.
  623. */
  624. public static function copyFile($bucket, $srcFpath, $dstFpath, $overwrite = false) {
  625. $url = self::generateResUrl($bucket, $srcFpath);
  626. $sign = Auth::createNonreusableSignature($bucket, $srcFpath);
  627. $data = array(
  628. 'op' => 'copy',
  629. 'dest_fileid' => $dstFpath,
  630. 'to_over_write' => $overwrite ? 1 : 0,
  631. );
  632. $req = array(
  633. 'url' => $url,
  634. 'method' => 'post',
  635. 'timeout' => self::$timeout,
  636. 'data' => $data,
  637. 'header' => array(
  638. 'Authorization: ' . $sign,
  639. ),
  640. );
  641. return self::sendRequest($req);
  642. }
  643. /**
  644. * Move a file.
  645. * @param $bucket bucket name.
  646. * @param $srcFpath source file path.
  647. * @param $dstFpath destination file path.
  648. * @param $overwrite if the destination location is occupied, overwrite it or not?
  649. * @return array|mixed.
  650. */
  651. public static function moveFile($bucket, $srcFpath, $dstFpath, $overwrite = false) {
  652. $url = self::generateResUrl($bucket, $srcFpath);
  653. $sign = Auth::createNonreusableSignature($bucket, $srcFpath);
  654. $data = array(
  655. 'op' => 'move',
  656. 'dest_fileid' => $dstFpath,
  657. 'to_over_write' => $overwrite ? 1 : 0,
  658. );
  659. $req = array(
  660. 'url' => $url,
  661. 'method' => 'post',
  662. 'timeout' => self::$timeout,
  663. 'data' => $data,
  664. 'header' => array(
  665. 'Authorization: ' . $sign,
  666. ),
  667. );
  668. return self::sendRequest($req);
  669. }
  670. }