You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2739 lines
99 KiB

6 years ago
  1. <?php
  2. namespace OSS;
  3. use OSS\Core\MimeTypes;
  4. use OSS\Core\OssException;
  5. use OSS\Http\RequestCore;
  6. use OSS\Http\RequestCore_Exception;
  7. use OSS\Http\ResponseCore;
  8. use OSS\Model\CorsConfig;
  9. use OSS\Model\CnameConfig;
  10. use OSS\Model\LoggingConfig;
  11. use OSS\Model\LiveChannelConfig;
  12. use OSS\Model\LiveChannelInfo;
  13. use OSS\Model\LiveChannelListInfo;
  14. use OSS\Model\StorageCapacityConfig;
  15. use OSS\Result\AclResult;
  16. use OSS\Result\BodyResult;
  17. use OSS\Result\GetCorsResult;
  18. use OSS\Result\GetLifecycleResult;
  19. use OSS\Result\GetLoggingResult;
  20. use OSS\Result\GetRefererResult;
  21. use OSS\Result\GetWebsiteResult;
  22. use OSS\Result\GetCnameResult;
  23. use OSS\Result\GetLocationResult;
  24. use OSS\Result\HeaderResult;
  25. use OSS\Result\InitiateMultipartUploadResult;
  26. use OSS\Result\ListBucketsResult;
  27. use OSS\Result\ListMultipartUploadResult;
  28. use OSS\Model\ListMultipartUploadInfo;
  29. use OSS\Result\ListObjectsResult;
  30. use OSS\Result\ListPartsResult;
  31. use OSS\Result\PutSetDeleteResult;
  32. use OSS\Result\DeleteObjectsResult;
  33. use OSS\Result\CopyObjectResult;
  34. use OSS\Result\CallbackResult;
  35. use OSS\Result\ExistResult;
  36. use OSS\Result\PutLiveChannelResult;
  37. use OSS\Result\GetLiveChannelHistoryResult;
  38. use OSS\Result\GetLiveChannelInfoResult;
  39. use OSS\Result\GetLiveChannelStatusResult;
  40. use OSS\Result\ListLiveChannelResult;
  41. use OSS\Result\GetStorageCapacityResult;
  42. use OSS\Result\AppendResult;
  43. use OSS\Model\ObjectListInfo;
  44. use OSS\Result\UploadPartResult;
  45. use OSS\Model\BucketListInfo;
  46. use OSS\Model\LifecycleConfig;
  47. use OSS\Model\RefererConfig;
  48. use OSS\Model\WebsiteConfig;
  49. use OSS\Core\OssUtil;
  50. use OSS\Model\ListPartsInfo;
  51. use OSS\Result\SymlinkResult;
  52. /**
  53. * Class OssClient
  54. *
  55. * Object Storage Service(OSS) 的客户端类,封装了用户通过OSS API对OSS服务的各种操作,
  56. * 用户通过OssClient实例可以进行Bucket,Object,MultipartUpload, ACL等操作,具体
  57. * 的接口规则可以参考官方OSS API文档
  58. */
  59. class OssClient
  60. {
  61. /**
  62. * 构造函数
  63. *
  64. * 构造函数有几种情况:
  65. * 1. 一般的时候初始化使用 $ossClient = new OssClient($id, $key, $endpoint)
  66. * 2. 如果使用CNAME的,比如使用的是www.testoss.com,在控制台上做了CNAME的绑定,
  67. * 初始化使用 $ossClient = new OssClient($id, $key, $endpoint, true)
  68. * 3. 如果使用了阿里云SecurityTokenService(STS),获得了AccessKeyID, AccessKeySecret, Token
  69. * 初始化使用 $ossClient = new OssClient($id, $key, $endpoint, false, $token)
  70. * 4. 如果用户使用的endpoint是ip
  71. * 初始化使用 $ossClient = new OssClient($id, $key, “1.2.3.4:8900)
  72. *
  73. * @param string $accessKeyId 从OSS获得的AccessKeyId
  74. * @param string $accessKeySecret 从OSS获得的AccessKeySecret
  75. * @param string $endpoint 您选定的OSS数据中心访问域名,例如oss-cn-hangzhou.aliyuncs.com
  76. * @param boolean $isCName 是否对Bucket做了域名绑定,并且Endpoint参数填写的是自己的域名
  77. * @param string $securityToken
  78. * @param string $requestProxy 添加代理支持
  79. * @throws OssException
  80. */
  81. public function __construct($accessKeyId, $accessKeySecret, $endpoint, $isCName = false, $securityToken = NULL, $requestProxy = NULL)
  82. {
  83. $accessKeyId = trim($accessKeyId);
  84. $accessKeySecret = trim($accessKeySecret);
  85. $endpoint = trim(trim($endpoint), "/");
  86. if (empty($accessKeyId)) {
  87. throw new OssException("access key id is empty");
  88. }
  89. if (empty($accessKeySecret)) {
  90. throw new OssException("access key secret is empty");
  91. }
  92. if (empty($endpoint)) {
  93. throw new OssException("endpoint is empty");
  94. }
  95. $this->hostname = $this->checkEndpoint($endpoint, $isCName);
  96. $this->accessKeyId = $accessKeyId;
  97. $this->accessKeySecret = $accessKeySecret;
  98. $this->securityToken = $securityToken;
  99. $this->requestProxy = $requestProxy;
  100. self::checkEnv();
  101. }
  102. /**
  103. * 列举用户所有的Bucket[GetService], Endpoint类型为cname不能进行此操作
  104. *
  105. * @param array $options
  106. * @throws OssException
  107. * @return BucketListInfo
  108. */
  109. public function listBuckets($options = NULL)
  110. {
  111. if ($this->hostType === self::OSS_HOST_TYPE_CNAME) {
  112. throw new OssException("operation is not permitted with CName host");
  113. }
  114. $this->precheckOptions($options);
  115. $options[self::OSS_BUCKET] = '';
  116. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  117. $options[self::OSS_OBJECT] = '/';
  118. $response = $this->auth($options);
  119. $result = new ListBucketsResult($response);
  120. return $result->getData();
  121. }
  122. /**
  123. * 创建bucket,默认创建的bucket的ACL是OssClient::OSS_ACL_TYPE_PRIVATE
  124. *
  125. * @param string $bucket
  126. * @param string $acl
  127. * @param array $options
  128. * @param string $storageType
  129. * @return null
  130. */
  131. public function createBucket($bucket, $acl = self::OSS_ACL_TYPE_PRIVATE, $options = NULL)
  132. {
  133. $this->precheckCommon($bucket, NULL, $options, false);
  134. $options[self::OSS_BUCKET] = $bucket;
  135. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  136. $options[self::OSS_OBJECT] = '/';
  137. $options[self::OSS_HEADERS] = array(self::OSS_ACL => $acl);
  138. if (isset($options[self::OSS_STORAGE])) {
  139. $this->precheckStorage($options[self::OSS_STORAGE]);
  140. $options[self::OSS_CONTENT] = OssUtil::createBucketXmlBody($options[self::OSS_STORAGE]);
  141. unset($options[self::OSS_STORAGE]);
  142. }
  143. $response = $this->auth($options);
  144. $result = new PutSetDeleteResult($response);
  145. return $result->getData();
  146. }
  147. /**
  148. * 删除bucket
  149. * 如果Bucket不为空(Bucket中有Object,或者有分块上传的碎片),则Bucket无法删除,
  150. * 必须删除Bucket中的所有Object以及碎片后,Bucket才能成功删除。
  151. *
  152. * @param string $bucket
  153. * @param array $options
  154. * @return null
  155. */
  156. public function deleteBucket($bucket, $options = NULL)
  157. {
  158. $this->precheckCommon($bucket, NULL, $options, false);
  159. $options[self::OSS_BUCKET] = $bucket;
  160. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  161. $options[self::OSS_OBJECT] = '/';
  162. $response = $this->auth($options);
  163. $result = new PutSetDeleteResult($response);
  164. return $result->getData();
  165. }
  166. /**
  167. * 判断bucket是否存在
  168. *
  169. * @param string $bucket
  170. * @return bool
  171. * @throws OssException
  172. */
  173. public function doesBucketExist($bucket)
  174. {
  175. $this->precheckCommon($bucket, NULL, $options, false);
  176. $options[self::OSS_BUCKET] = $bucket;
  177. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  178. $options[self::OSS_OBJECT] = '/';
  179. $options[self::OSS_SUB_RESOURCE] = 'acl';
  180. $response = $this->auth($options);
  181. $result = new ExistResult($response);
  182. return $result->getData();
  183. }
  184. /**
  185. * 获取bucket所属的数据中心位置信息
  186. *
  187. * @param string $bucket
  188. * @param array $options
  189. * @throws OssException
  190. * @return string
  191. */
  192. public function getBucketLocation($bucket, $options = NULL)
  193. {
  194. $this->precheckCommon($bucket, NULL, $options, false);
  195. $options[self::OSS_BUCKET] = $bucket;
  196. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  197. $options[self::OSS_OBJECT] = '/';
  198. $options[self::OSS_SUB_RESOURCE] = 'location';
  199. $response = $this->auth($options);
  200. $result = new GetLocationResult($response);
  201. return $result->getData();
  202. }
  203. /**
  204. * 获取Bucket的Meta信息
  205. *
  206. * @param string $bucket
  207. * @param array $options 具体参考SDK文档
  208. * @return array
  209. */
  210. public function getBucketMeta($bucket, $options = NULL)
  211. {
  212. $this->precheckCommon($bucket, NULL, $options, false);
  213. $options[self::OSS_BUCKET] = $bucket;
  214. $options[self::OSS_METHOD] = self::OSS_HTTP_HEAD;
  215. $options[self::OSS_OBJECT] = '/';
  216. $response = $this->auth($options);
  217. $result = new HeaderResult($response);
  218. return $result->getData();
  219. }
  220. /**
  221. * 获取bucket的ACL配置情况
  222. *
  223. * @param string $bucket
  224. * @param array $options
  225. * @throws OssException
  226. * @return string
  227. */
  228. public function getBucketAcl($bucket, $options = NULL)
  229. {
  230. $this->precheckCommon($bucket, NULL, $options, false);
  231. $options[self::OSS_BUCKET] = $bucket;
  232. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  233. $options[self::OSS_OBJECT] = '/';
  234. $options[self::OSS_SUB_RESOURCE] = 'acl';
  235. $response = $this->auth($options);
  236. $result = new AclResult($response);
  237. return $result->getData();
  238. }
  239. /**
  240. * 设置bucket的ACL配置情况
  241. *
  242. * @param string $bucket bucket名称
  243. * @param string $acl 读写权限,可选值 ['private', 'public-read', 'public-read-write']
  244. * @param array $options 可以为空
  245. * @throws OssException
  246. * @return null
  247. */
  248. public function putBucketAcl($bucket, $acl, $options = NULL)
  249. {
  250. $this->precheckCommon($bucket, NULL, $options, false);
  251. $options[self::OSS_BUCKET] = $bucket;
  252. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  253. $options[self::OSS_OBJECT] = '/';
  254. $options[self::OSS_HEADERS] = array(self::OSS_ACL => $acl);
  255. $options[self::OSS_SUB_RESOURCE] = 'acl';
  256. $response = $this->auth($options);
  257. $result = new PutSetDeleteResult($response);
  258. return $result->getData();
  259. }
  260. /**
  261. * 获取object的ACL属性
  262. *
  263. * @param string $bucket
  264. * @param string $object
  265. * @throws OssException
  266. * @return string
  267. */
  268. public function getObjectAcl($bucket, $object)
  269. {
  270. $options = array();
  271. $this->precheckCommon($bucket, $object, $options, true);
  272. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  273. $options[self::OSS_BUCKET] = $bucket;
  274. $options[self::OSS_OBJECT] = $object;
  275. $options[self::OSS_SUB_RESOURCE] = 'acl';
  276. $response = $this->auth($options);
  277. $result = new AclResult($response);
  278. return $result->getData();
  279. }
  280. /**
  281. * 设置object的ACL属性
  282. *
  283. * @param string $bucket bucket名称
  284. * @param string $object object名称
  285. * @param string $acl 读写权限,可选值 ['default', 'private', 'public-read', 'public-read-write']
  286. * @throws OssException
  287. * @return null
  288. */
  289. public function putObjectAcl($bucket, $object, $acl)
  290. {
  291. $this->precheckCommon($bucket, $object, $options, true);
  292. $options[self::OSS_BUCKET] = $bucket;
  293. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  294. $options[self::OSS_OBJECT] = $object;
  295. $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_ACL => $acl);
  296. $options[self::OSS_SUB_RESOURCE] = 'acl';
  297. $response = $this->auth($options);
  298. $result = new PutSetDeleteResult($response);
  299. return $result->getData();
  300. }
  301. /**
  302. * 获取Bucket的访问日志配置情况
  303. *
  304. * @param string $bucket bucket名称
  305. * @param array $options 可以为空
  306. * @throws OssException
  307. * @return LoggingConfig
  308. */
  309. public function getBucketLogging($bucket, $options = NULL)
  310. {
  311. $this->precheckCommon($bucket, NULL, $options, false);
  312. $options[self::OSS_BUCKET] = $bucket;
  313. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  314. $options[self::OSS_OBJECT] = '/';
  315. $options[self::OSS_SUB_RESOURCE] = 'logging';
  316. $response = $this->auth($options);
  317. $result = new GetLoggingResult($response);
  318. return $result->getData();
  319. }
  320. /**
  321. * 开启Bucket访问日志记录功能,只有Bucket的所有者才能更改
  322. *
  323. * @param string $bucket bucket名称
  324. * @param string $targetBucket 日志文件存放的bucket
  325. * @param string $targetPrefix 日志的文件前缀
  326. * @param array $options 可以为空
  327. * @throws OssException
  328. * @return null
  329. */
  330. public function putBucketLogging($bucket, $targetBucket, $targetPrefix, $options = NULL)
  331. {
  332. $this->precheckCommon($bucket, NULL, $options, false);
  333. $this->precheckBucket($targetBucket, 'targetbucket is not allowed empty');
  334. $options[self::OSS_BUCKET] = $bucket;
  335. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  336. $options[self::OSS_OBJECT] = '/';
  337. $options[self::OSS_SUB_RESOURCE] = 'logging';
  338. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  339. $loggingConfig = new LoggingConfig($targetBucket, $targetPrefix);
  340. $options[self::OSS_CONTENT] = $loggingConfig->serializeToXml();
  341. $response = $this->auth($options);
  342. $result = new PutSetDeleteResult($response);
  343. return $result->getData();
  344. }
  345. /**
  346. * 关闭bucket访问日志记录功能
  347. *
  348. * @param string $bucket bucket名称
  349. * @param array $options 可以为空
  350. * @throws OssException
  351. * @return null
  352. */
  353. public function deleteBucketLogging($bucket, $options = NULL)
  354. {
  355. $this->precheckCommon($bucket, NULL, $options, false);
  356. $options[self::OSS_BUCKET] = $bucket;
  357. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  358. $options[self::OSS_OBJECT] = '/';
  359. $options[self::OSS_SUB_RESOURCE] = 'logging';
  360. $response = $this->auth($options);
  361. $result = new PutSetDeleteResult($response);
  362. return $result->getData();
  363. }
  364. /**
  365. * 将bucket设置成静态网站托管模式
  366. *
  367. * @param string $bucket bucket名称
  368. * @param WebsiteConfig $websiteConfig
  369. * @param array $options 可以为空
  370. * @throws OssException
  371. * @return null
  372. */
  373. public function putBucketWebsite($bucket, $websiteConfig, $options = NULL)
  374. {
  375. $this->precheckCommon($bucket, NULL, $options, false);
  376. $options[self::OSS_BUCKET] = $bucket;
  377. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  378. $options[self::OSS_OBJECT] = '/';
  379. $options[self::OSS_SUB_RESOURCE] = 'website';
  380. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  381. $options[self::OSS_CONTENT] = $websiteConfig->serializeToXml();
  382. $response = $this->auth($options);
  383. $result = new PutSetDeleteResult($response);
  384. return $result->getData();
  385. }
  386. /**
  387. * 获取bucket的静态网站托管状态
  388. *
  389. * @param string $bucket bucket名称
  390. * @param array $options
  391. * @throws OssException
  392. * @return WebsiteConfig
  393. */
  394. public function getBucketWebsite($bucket, $options = NULL)
  395. {
  396. $this->precheckCommon($bucket, NULL, $options, false);
  397. $options[self::OSS_BUCKET] = $bucket;
  398. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  399. $options[self::OSS_OBJECT] = '/';
  400. $options[self::OSS_SUB_RESOURCE] = 'website';
  401. $response = $this->auth($options);
  402. $result = new GetWebsiteResult($response);
  403. return $result->getData();
  404. }
  405. /**
  406. * 关闭bucket的静态网站托管模式
  407. *
  408. * @param string $bucket bucket名称
  409. * @param array $options
  410. * @throws OssException
  411. * @return null
  412. */
  413. public function deleteBucketWebsite($bucket, $options = NULL)
  414. {
  415. $this->precheckCommon($bucket, NULL, $options, false);
  416. $options[self::OSS_BUCKET] = $bucket;
  417. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  418. $options[self::OSS_OBJECT] = '/';
  419. $options[self::OSS_SUB_RESOURCE] = 'website';
  420. $response = $this->auth($options);
  421. $result = new PutSetDeleteResult($response);
  422. return $result->getData();
  423. }
  424. /**
  425. * 在指定的bucket上设定一个跨域资源共享(CORS)的规则,如果原规则存在则覆盖原规则
  426. *
  427. * @param string $bucket bucket名称
  428. * @param CorsConfig $corsConfig 跨域资源共享配置,具体规则参见SDK文档
  429. * @param array $options array
  430. * @throws OssException
  431. * @return null
  432. */
  433. public function putBucketCors($bucket, $corsConfig, $options = NULL)
  434. {
  435. $this->precheckCommon($bucket, NULL, $options, false);
  436. $options[self::OSS_BUCKET] = $bucket;
  437. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  438. $options[self::OSS_OBJECT] = '/';
  439. $options[self::OSS_SUB_RESOURCE] = 'cors';
  440. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  441. $options[self::OSS_CONTENT] = $corsConfig->serializeToXml();
  442. $response = $this->auth($options);
  443. $result = new PutSetDeleteResult($response);
  444. return $result->getData();
  445. }
  446. /**
  447. * 获取Bucket的CORS配置情况
  448. *
  449. * @param string $bucket bucket名称
  450. * @param array $options 可以为空
  451. * @throws OssException
  452. * @return CorsConfig
  453. */
  454. public function getBucketCors($bucket, $options = NULL)
  455. {
  456. $this->precheckCommon($bucket, NULL, $options, false);
  457. $options[self::OSS_BUCKET] = $bucket;
  458. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  459. $options[self::OSS_OBJECT] = '/';
  460. $options[self::OSS_SUB_RESOURCE] = 'cors';
  461. $response = $this->auth($options);
  462. $result = new GetCorsResult($response, __FUNCTION__);
  463. return $result->getData();
  464. }
  465. /**
  466. * 关闭指定Bucket对应的CORS功能并清空所有规则
  467. *
  468. * @param string $bucket bucket名称
  469. * @param array $options
  470. * @throws OssException
  471. * @return null
  472. */
  473. public function deleteBucketCors($bucket, $options = NULL)
  474. {
  475. $this->precheckCommon($bucket, NULL, $options, false);
  476. $options[self::OSS_BUCKET] = $bucket;
  477. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  478. $options[self::OSS_OBJECT] = '/';
  479. $options[self::OSS_SUB_RESOURCE] = 'cors';
  480. $response = $this->auth($options);
  481. $result = new PutSetDeleteResult($response);
  482. return $result->getData();
  483. }
  484. /**
  485. * 为指定Bucket增加CNAME绑定
  486. *
  487. * @param string $bucket bucket名称
  488. * @param string $cname
  489. * @param array $options
  490. * @throws OssException
  491. * @return null
  492. */
  493. public function addBucketCname($bucket, $cname, $options = NULL)
  494. {
  495. $this->precheckCommon($bucket, NULL, $options, false);
  496. $options[self::OSS_BUCKET] = $bucket;
  497. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  498. $options[self::OSS_OBJECT] = '/';
  499. $options[self::OSS_SUB_RESOURCE] = 'cname';
  500. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  501. $cnameConfig = new CnameConfig();
  502. $cnameConfig->addCname($cname);
  503. $options[self::OSS_CONTENT] = $cnameConfig->serializeToXml();
  504. $options[self::OSS_COMP] = 'add';
  505. $response = $this->auth($options);
  506. $result = new PutSetDeleteResult($response);
  507. return $result->getData();
  508. }
  509. /**
  510. * 获取指定Bucket已绑定的CNAME列表
  511. *
  512. * @param string $bucket bucket名称
  513. * @param array $options
  514. * @throws OssException
  515. * @return CnameConfig
  516. */
  517. public function getBucketCname($bucket, $options = NULL)
  518. {
  519. $this->precheckCommon($bucket, NULL, $options, false);
  520. $options[self::OSS_BUCKET] = $bucket;
  521. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  522. $options[self::OSS_OBJECT] = '/';
  523. $options[self::OSS_SUB_RESOURCE] = 'cname';
  524. $response = $this->auth($options);
  525. $result = new GetCnameResult($response);
  526. return $result->getData();
  527. }
  528. /**
  529. * 解除指定Bucket的CNAME绑定
  530. *
  531. * @param string $bucket bucket名称
  532. * @param CnameConfig $cnameConfig
  533. * @param array $options
  534. * @throws OssException
  535. * @return null
  536. */
  537. public function deleteBucketCname($bucket, $cname, $options = NULL)
  538. {
  539. $this->precheckCommon($bucket, NULL, $options, false);
  540. $options[self::OSS_BUCKET] = $bucket;
  541. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  542. $options[self::OSS_OBJECT] = '/';
  543. $options[self::OSS_SUB_RESOURCE] = 'cname';
  544. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  545. $cnameConfig = new CnameConfig();
  546. $cnameConfig->addCname($cname);
  547. $options[self::OSS_CONTENT] = $cnameConfig->serializeToXml();
  548. $options[self::OSS_COMP] = 'delete';
  549. $response = $this->auth($options);
  550. $result = new PutSetDeleteResult($response);
  551. return $result->getData();
  552. }
  553. /**
  554. * 为指定Bucket创建LiveChannel
  555. *
  556. * @param string $bucket bucket名称
  557. * @param string channelName $channelName
  558. * @param LiveChannelConfig $channelConfig
  559. * @param array $options
  560. * @throws OssException
  561. * @return LiveChannelInfo
  562. */
  563. public function putBucketLiveChannel($bucket, $channelName, $channelConfig, $options = NULL)
  564. {
  565. $this->precheckCommon($bucket, NULL, $options, false);
  566. $options[self::OSS_BUCKET] = $bucket;
  567. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  568. $options[self::OSS_OBJECT] = $channelName;
  569. $options[self::OSS_SUB_RESOURCE] = 'live';
  570. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  571. $options[self::OSS_CONTENT] = $channelConfig->serializeToXml();
  572. $response = $this->auth($options);
  573. $result = new PutLiveChannelResult($response);
  574. $info = $result->getData();
  575. $info->setName($channelName);
  576. $info->setDescription($channelConfig->getDescription());
  577. return $info;
  578. }
  579. /**
  580. * 设置LiveChannel的status
  581. *
  582. * @param string $bucket bucket名称
  583. * @param string channelName $channelName
  584. * @param string channelStatus $channelStatus 为enabled或disabled
  585. * @param array $options
  586. * @throws OssException
  587. * @return null
  588. */
  589. public function putLiveChannelStatus($bucket, $channelName, $channelStatus, $options = NULL)
  590. {
  591. $this->precheckCommon($bucket, NULL, $options, false);
  592. $options[self::OSS_BUCKET] = $bucket;
  593. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  594. $options[self::OSS_OBJECT] = $channelName;
  595. $options[self::OSS_SUB_RESOURCE] = 'live';
  596. $options[self::OSS_LIVE_CHANNEL_STATUS] = $channelStatus;
  597. $response = $this->auth($options);
  598. $result = new PutSetDeleteResult($response);
  599. return $result->getData();
  600. }
  601. /**
  602. * 获取LiveChannel信息
  603. *
  604. * @param string $bucket bucket名称
  605. * @param string channelName $channelName
  606. * @param array $options
  607. * @throws OssException
  608. * @return GetLiveChannelInfo
  609. */
  610. public function getLiveChannelInfo($bucket, $channelName, $options = NULL)
  611. {
  612. $this->precheckCommon($bucket, NULL, $options, false);
  613. $options[self::OSS_BUCKET] = $bucket;
  614. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  615. $options[self::OSS_OBJECT] = $channelName;
  616. $options[self::OSS_SUB_RESOURCE] = 'live';
  617. $response = $this->auth($options);
  618. $result = new GetLiveChannelInfoResult($response);
  619. return $result->getData();
  620. }
  621. /**
  622. * 获取LiveChannel状态信息
  623. *
  624. * @param string $bucket bucket名称
  625. * @param string channelName $channelName
  626. * @param array $options
  627. * @throws OssException
  628. * @return GetLiveChannelStatus
  629. */
  630. public function getLiveChannelStatus($bucket, $channelName, $options = NULL)
  631. {
  632. $this->precheckCommon($bucket, NULL, $options, false);
  633. $options[self::OSS_BUCKET] = $bucket;
  634. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  635. $options[self::OSS_OBJECT] = $channelName;
  636. $options[self::OSS_SUB_RESOURCE] = 'live';
  637. $options[self::OSS_COMP] = 'stat';
  638. $response = $this->auth($options);
  639. $result = new GetLiveChannelStatusResult($response);
  640. return $result->getData();
  641. }
  642. /**
  643. *获取LiveChannel推流记录
  644. *
  645. * @param string $bucket bucket名称
  646. * @param string channelName $channelName
  647. * @param array $options
  648. * @throws OssException
  649. * @return GetLiveChannelHistory
  650. */
  651. public function getLiveChannelHistory($bucket, $channelName, $options = NULL)
  652. {
  653. $this->precheckCommon($bucket, NULL, $options, false);
  654. $options[self::OSS_BUCKET] = $bucket;
  655. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  656. $options[self::OSS_OBJECT] = $channelName;
  657. $options[self::OSS_SUB_RESOURCE] = 'live';
  658. $options[self::OSS_COMP] = 'history';
  659. $response = $this->auth($options);
  660. $result = new GetLiveChannelHistoryResult($response);
  661. return $result->getData();
  662. }
  663. /**
  664. *获取指定Bucket下的live channel列表
  665. *
  666. * @param string $bucket bucket名称
  667. * @param array $options
  668. * @throws OssException
  669. * @return LiveChannelListInfo
  670. */
  671. public function listBucketLiveChannels($bucket, $options = NULL)
  672. {
  673. $this->precheckCommon($bucket, NULL, $options, false);
  674. $options[self::OSS_BUCKET] = $bucket;
  675. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  676. $options[self::OSS_OBJECT] = '/';
  677. $options[self::OSS_SUB_RESOURCE] = 'live';
  678. $options[self::OSS_QUERY_STRING] = array(
  679. 'prefix' => isset($options['prefix']) ? $options['prefix'] : '',
  680. 'marker' => isset($options['marker']) ? $options['marker'] : '',
  681. 'max-keys' => isset($options['max-keys']) ? $options['max-keys'] : '',
  682. );
  683. $response = $this->auth($options);
  684. $result = new ListLiveChannelResult($response);
  685. $list = $result->getData();
  686. $list->setBucketName($bucket);
  687. return $list;
  688. }
  689. /**
  690. * 为指定LiveChannel生成播放列表
  691. *
  692. * @param string $bucket bucket名称
  693. * @param string channelName $channelName
  694. * @param string $playlistName 指定生成的点播播放列表的名称,必须以“.m3u8”结尾
  695. * @param array $setTime startTime和EndTime以unix时间戳格式给定,跨度不能超过一天
  696. * @throws OssException
  697. * @return null
  698. */
  699. public function postVodPlaylist($bucket, $channelName, $playlistName, $setTime)
  700. {
  701. $this->precheckCommon($bucket, NULL, $options, false);
  702. $options[self::OSS_BUCKET] = $bucket;
  703. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  704. $options[self::OSS_OBJECT] = $channelName . '/' . $playlistName;
  705. $options[self::OSS_SUB_RESOURCE] = 'vod';
  706. $options[self::OSS_LIVE_CHANNEL_END_TIME] = $setTime['EndTime'];
  707. $options[self::OSS_LIVE_CHANNEL_START_TIME] = $setTime['StartTime'];
  708. $response = $this->auth($options);
  709. $result = new PutSetDeleteResult($response);
  710. return $result->getData();
  711. }
  712. /**
  713. * 删除指定Bucket的LiveChannel
  714. *
  715. * @param string $bucket bucket名称
  716. * @param string channelName $channelName
  717. * @param array $options
  718. * @throws OssException
  719. * @return null
  720. */
  721. public function deleteBucketLiveChannel($bucket, $channelName, $options = NULL)
  722. {
  723. $this->precheckCommon($bucket, NULL, $options, false);
  724. $options[self::OSS_BUCKET] = $bucket;
  725. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  726. $options[self::OSS_OBJECT] = $channelName;
  727. $options[self::OSS_SUB_RESOURCE] = 'live';
  728. $response = $this->auth($options);
  729. $result = new PutSetDeleteResult($response);
  730. return $result->getData();
  731. }
  732. /**
  733. * 生成带签名的推流地址
  734. *
  735. * @param string $bucket bucket名称
  736. * @param string channelName $channelName
  737. * @param int timeout 设置超时时间,单位为秒
  738. * @param array $options
  739. * @throws OssException
  740. * @return 推流地址
  741. */
  742. public function signRtmpUrl($bucket, $channelName, $timeout = 60, $options = NULL)
  743. {
  744. $this->precheckCommon($bucket, $channelName, $options, false);
  745. $expires = time() + $timeout;
  746. $proto = 'rtmp://';
  747. $hostname = $this->generateHostname($bucket);
  748. $cano_params = '';
  749. $query_items = array();
  750. $params = isset($options['params']) ? $options['params'] : array();
  751. uksort($params, 'strnatcasecmp');
  752. foreach ($params as $key => $value) {
  753. $cano_params = $cano_params . $key . ':' . $value . "\n";
  754. $query_items[] = rawurlencode($key) . '=' . rawurlencode($value);
  755. }
  756. $resource = '/' . $bucket . '/' . $channelName;
  757. $string_to_sign = $expires . "\n" . $cano_params . $resource;
  758. $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->accessKeySecret, true));
  759. $query_items[] = 'OSSAccessKeyId=' . rawurlencode($this->accessKeyId);
  760. $query_items[] = 'Expires=' . rawurlencode($expires);
  761. $query_items[] = 'Signature=' . rawurlencode($signature);
  762. return $proto . $hostname . '/live/' . $channelName . '?' . implode('&', $query_items);
  763. }
  764. /**
  765. * 检验跨域资源请求, 发送跨域请求之前会发送一个preflight请求(OPTIONS)并带上特定的来源域,
  766. * HTTP方法和header信息等给OSS以决定是否发送真正的请求。 OSS可以通过putBucketCors接口
  767. * 来开启Bucket的CORS支持,开启CORS功能之后,OSS在收到浏览器preflight请求时会根据设定的
  768. * 规则评估是否允许本次请求
  769. *
  770. * @param string $bucket bucket名称
  771. * @param string $object object名称
  772. * @param string $origin 请求来源域
  773. * @param string $request_method 表明实际请求中会使用的HTTP方法
  774. * @param string $request_headers 表明实际请求中会使用的除了简单头部之外的headers
  775. * @param array $options
  776. * @return array
  777. * @throws OssException
  778. * @link http://help.aliyun.com/document_detail/oss/api-reference/cors/OptionObject.html
  779. */
  780. public function optionsObject($bucket, $object, $origin, $request_method, $request_headers, $options = NULL)
  781. {
  782. $this->precheckCommon($bucket, NULL, $options, false);
  783. $options[self::OSS_BUCKET] = $bucket;
  784. $options[self::OSS_METHOD] = self::OSS_HTTP_OPTIONS;
  785. $options[self::OSS_OBJECT] = $object;
  786. $options[self::OSS_HEADERS] = array(
  787. self::OSS_OPTIONS_ORIGIN => $origin,
  788. self::OSS_OPTIONS_REQUEST_HEADERS => $request_headers,
  789. self::OSS_OPTIONS_REQUEST_METHOD => $request_method
  790. );
  791. $response = $this->auth($options);
  792. $result = new HeaderResult($response);
  793. return $result->getData();
  794. }
  795. /**
  796. * 设置Bucket的Lifecycle配置
  797. *
  798. * @param string $bucket bucket名称
  799. * @param LifecycleConfig $lifecycleConfig Lifecycle配置类
  800. * @param array $options
  801. * @throws OssException
  802. * @return null
  803. */
  804. public function putBucketLifecycle($bucket, $lifecycleConfig, $options = NULL)
  805. {
  806. $this->precheckCommon($bucket, NULL, $options, false);
  807. $options[self::OSS_BUCKET] = $bucket;
  808. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  809. $options[self::OSS_OBJECT] = '/';
  810. $options[self::OSS_SUB_RESOURCE] = 'lifecycle';
  811. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  812. $options[self::OSS_CONTENT] = $lifecycleConfig->serializeToXml();
  813. $response = $this->auth($options);
  814. $result = new PutSetDeleteResult($response);
  815. return $result->getData();
  816. }
  817. /**
  818. * 获取Bucket的Lifecycle配置情况
  819. *
  820. * @param string $bucket bucket名称
  821. * @param array $options
  822. * @throws OssException
  823. * @return LifecycleConfig
  824. */
  825. public function getBucketLifecycle($bucket, $options = NULL)
  826. {
  827. $this->precheckCommon($bucket, NULL, $options, false);
  828. $options[self::OSS_BUCKET] = $bucket;
  829. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  830. $options[self::OSS_OBJECT] = '/';
  831. $options[self::OSS_SUB_RESOURCE] = 'lifecycle';
  832. $response = $this->auth($options);
  833. $result = new GetLifecycleResult($response);
  834. return $result->getData();
  835. }
  836. /**
  837. * 删除指定Bucket的生命周期配置
  838. *
  839. * @param string $bucket bucket名称
  840. * @param array $options
  841. * @throws OssException
  842. * @return null
  843. */
  844. public function deleteBucketLifecycle($bucket, $options = NULL)
  845. {
  846. $this->precheckCommon($bucket, NULL, $options, false);
  847. $options[self::OSS_BUCKET] = $bucket;
  848. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  849. $options[self::OSS_OBJECT] = '/';
  850. $options[self::OSS_SUB_RESOURCE] = 'lifecycle';
  851. $response = $this->auth($options);
  852. $result = new PutSetDeleteResult($response);
  853. return $result->getData();
  854. }
  855. /**
  856. * 设置一个bucket的referer访问白名单和是否允许referer字段为空的请求访问
  857. * Bucket Referer防盗链具体见OSS防盗链
  858. *
  859. * @param string $bucket bucket名称
  860. * @param RefererConfig $refererConfig
  861. * @param array $options
  862. * @return ResponseCore
  863. * @throws null
  864. */
  865. public function putBucketReferer($bucket, $refererConfig, $options = NULL)
  866. {
  867. $this->precheckCommon($bucket, NULL, $options, false);
  868. $options[self::OSS_BUCKET] = $bucket;
  869. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  870. $options[self::OSS_OBJECT] = '/';
  871. $options[self::OSS_SUB_RESOURCE] = 'referer';
  872. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  873. $options[self::OSS_CONTENT] = $refererConfig->serializeToXml();
  874. $response = $this->auth($options);
  875. $result = new PutSetDeleteResult($response);
  876. return $result->getData();
  877. }
  878. /**
  879. * 获取Bucket的Referer配置情况
  880. * Bucket Referer防盗链具体见OSS防盗链
  881. *
  882. * @param string $bucket bucket名称
  883. * @param array $options
  884. * @throws OssException
  885. * @return RefererConfig
  886. */
  887. public function getBucketReferer($bucket, $options = NULL)
  888. {
  889. $this->precheckCommon($bucket, NULL, $options, false);
  890. $options[self::OSS_BUCKET] = $bucket;
  891. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  892. $options[self::OSS_OBJECT] = '/';
  893. $options[self::OSS_SUB_RESOURCE] = 'referer';
  894. $response = $this->auth($options);
  895. $result = new GetRefererResult($response);
  896. return $result->getData();
  897. }
  898. /**
  899. * 设置bucket的容量大小,单位GB
  900. * 当bucket的容量大于设置的容量时,禁止继续写入
  901. *
  902. * @param string $bucket bucket名称
  903. * @param int $storageCapacity
  904. * @param array $options
  905. * @return ResponseCore
  906. * @throws null
  907. */
  908. public function putBucketStorageCapacity($bucket, $storageCapacity, $options = NULL)
  909. {
  910. $this->precheckCommon($bucket, NULL, $options, false);
  911. $options[self::OSS_BUCKET] = $bucket;
  912. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  913. $options[self::OSS_OBJECT] = '/';
  914. $options[self::OSS_SUB_RESOURCE] = 'qos';
  915. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  916. $storageCapacityConfig = new StorageCapacityConfig($storageCapacity);
  917. $options[self::OSS_CONTENT] = $storageCapacityConfig->serializeToXml();
  918. $response = $this->auth($options);
  919. $result = new PutSetDeleteResult($response);
  920. return $result->getData();
  921. }
  922. /**
  923. * 获取bucket的容量大小,单位GB
  924. *
  925. * @param string $bucket bucket名称
  926. * @param array $options
  927. * @throws OssException
  928. * @return int
  929. */
  930. public function getBucketStorageCapacity($bucket, $options = NULL)
  931. {
  932. $this->precheckCommon($bucket, NULL, $options, false);
  933. $options[self::OSS_BUCKET] = $bucket;
  934. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  935. $options[self::OSS_OBJECT] = '/';
  936. $options[self::OSS_SUB_RESOURCE] = 'qos';
  937. $response = $this->auth($options);
  938. $result = new GetStorageCapacityResult($response);
  939. return $result->getData();
  940. }
  941. /**
  942. * 获取bucket下的object列表
  943. *
  944. * @param string $bucket
  945. * @param array $options
  946. * 其中options中的参数如下
  947. * $options = array(
  948. * 'max-keys' => max-keys用于限定此次返回object的最大数,如果不设定,默认为100,max-keys取值不能大于1000。
  949. * 'prefix' => 限定返回的object key必须以prefix作为前缀。注意使用prefix查询时,返回的key中仍会包含prefix。
  950. * 'delimiter' => 是一个用于对Object名字进行分组的字符。所有名字包含指定的前缀且第一次出现delimiter字符之间的object作为一组元素
  951. * 'marker' => 用户设定结果从marker之后按字母排序的第一个开始返回。
  952. *)
  953. * 其中 prefix,marker用来实现分页显示效果,参数的长度必须小于256字节。
  954. * @throws OssException
  955. * @return ObjectListInfo
  956. */
  957. public function listObjects($bucket, $options = NULL)
  958. {
  959. $this->precheckCommon($bucket, NULL, $options, false);
  960. $options[self::OSS_BUCKET] = $bucket;
  961. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  962. $options[self::OSS_OBJECT] = '/';
  963. $options[self::OSS_HEADERS] = array(
  964. self::OSS_DELIMITER => isset($options[self::OSS_DELIMITER]) ? $options[self::OSS_DELIMITER] : '/',
  965. self::OSS_PREFIX => isset($options[self::OSS_PREFIX]) ? $options[self::OSS_PREFIX] : '',
  966. self::OSS_MAX_KEYS => isset($options[self::OSS_MAX_KEYS]) ? $options[self::OSS_MAX_KEYS] : self::OSS_MAX_KEYS_VALUE,
  967. self::OSS_MARKER => isset($options[self::OSS_MARKER]) ? $options[self::OSS_MARKER] : '',
  968. );
  969. $query = isset($options[self::OSS_QUERY_STRING]) ? $options[self::OSS_QUERY_STRING] : array();
  970. $options[self::OSS_QUERY_STRING] = array_merge(
  971. $query,
  972. array(self::OSS_ENCODING_TYPE => self::OSS_ENCODING_TYPE_URL)
  973. );
  974. $response = $this->auth($options);
  975. $result = new ListObjectsResult($response);
  976. return $result->getData();
  977. }
  978. /**
  979. * 创建虚拟目录 (本函数会在object名称后增加'/', 所以创建目录的object名称不需要'/'结尾,否则,目录名称会变成'//')
  980. *
  981. * 暂不开放此接口
  982. *
  983. * @param string $bucket bucket名称
  984. * @param string $object object名称
  985. * @param array $options
  986. * @return null
  987. */
  988. public function createObjectDir($bucket, $object, $options = NULL)
  989. {
  990. $this->precheckCommon($bucket, $object, $options);
  991. $options[self::OSS_BUCKET] = $bucket;
  992. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  993. $options[self::OSS_OBJECT] = $object . '/';
  994. $options[self::OSS_CONTENT_LENGTH] = array(self::OSS_CONTENT_LENGTH => 0);
  995. $response = $this->auth($options);
  996. $result = new PutSetDeleteResult($response);
  997. return $result->getData();
  998. }
  999. /**
  1000. * 上传内存中的内容
  1001. *
  1002. * @param string $bucket bucket名称
  1003. * @param string $object objcet名称
  1004. * @param string $content 上传的内容
  1005. * @param array $options
  1006. * @return null
  1007. */
  1008. public function putObject($bucket, $object, $content, $options = NULL)
  1009. {
  1010. $this->precheckCommon($bucket, $object, $options);
  1011. $options[self::OSS_CONTENT] = $content;
  1012. $options[self::OSS_BUCKET] = $bucket;
  1013. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  1014. $options[self::OSS_OBJECT] = $object;
  1015. if (!isset($options[self::OSS_LENGTH])) {
  1016. $options[self::OSS_CONTENT_LENGTH] = strlen($options[self::OSS_CONTENT]);
  1017. } else {
  1018. $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
  1019. }
  1020. $is_check_md5 = $this->isCheckMD5($options);
  1021. if ($is_check_md5) {
  1022. $content_md5 = base64_encode(md5($content, true));
  1023. $options[self::OSS_CONTENT_MD5] = $content_md5;
  1024. }
  1025. if (!isset($options[self::OSS_CONTENT_TYPE])) {
  1026. $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object);
  1027. }
  1028. $response = $this->auth($options);
  1029. if (isset($options[self::OSS_CALLBACK]) && !empty($options[self::OSS_CALLBACK])) {
  1030. $result = new CallbackResult($response);
  1031. } else {
  1032. $result = new PutSetDeleteResult($response);
  1033. }
  1034. return $result->getData();
  1035. }
  1036. /**
  1037. * 创建symlink
  1038. * @param string $bucket bucket名称
  1039. * @param string $symlink symlink名称
  1040. * @param string $targetObject 目标object名称
  1041. * @param array $options
  1042. * @return null
  1043. */
  1044. public function putSymlink($bucket, $symlink ,$targetObject, $options = NULL)
  1045. {
  1046. $this->precheckCommon($bucket, $symlink, $options);
  1047. $options[self::OSS_BUCKET] = $bucket;
  1048. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  1049. $options[self::OSS_OBJECT] = $symlink;
  1050. $options[self::OSS_SUB_RESOURCE] = self::OSS_SYMLINK;
  1051. $options[self::OSS_HEADERS][self::OSS_SYMLINK_TARGET] = rawurlencode($targetObject);
  1052. $response = $this->auth($options);
  1053. $result = new PutSetDeleteResult($response);
  1054. return $result->getData();
  1055. }
  1056. /**
  1057. * 获取symlink
  1058. *@param string $bucket bucket名称
  1059. * @param string $symlink symlink名称
  1060. * @return null
  1061. */
  1062. public function getSymlink($bucket, $symlink)
  1063. {
  1064. $this->precheckCommon($bucket, $symlink, $options);
  1065. $options[self::OSS_BUCKET] = $bucket;
  1066. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  1067. $options[self::OSS_OBJECT] = $symlink;
  1068. $options[self::OSS_SUB_RESOURCE] = self::OSS_SYMLINK;
  1069. $response = $this->auth($options);
  1070. $result = new SymlinkResult($response);
  1071. return $result->getData();
  1072. }
  1073. /**
  1074. * 上传本地文件
  1075. *
  1076. * @param string $bucket bucket名称
  1077. * @param string $object object名称
  1078. * @param string $file 本地文件路径
  1079. * @param array $options
  1080. * @return null
  1081. * @throws OssException
  1082. */
  1083. public function uploadFile($bucket, $object, $file, $options = NULL)
  1084. {
  1085. $this->precheckCommon($bucket, $object, $options);
  1086. OssUtil::throwOssExceptionWithMessageIfEmpty($file, "file path is invalid");
  1087. $file = OssUtil::encodePath($file);
  1088. if (!file_exists($file)) {
  1089. throw new OssException($file . " file does not exist");
  1090. }
  1091. $options[self::OSS_FILE_UPLOAD] = $file;
  1092. $file_size = filesize($options[self::OSS_FILE_UPLOAD]);
  1093. $is_check_md5 = $this->isCheckMD5($options);
  1094. if ($is_check_md5) {
  1095. $content_md5 = base64_encode(md5_file($options[self::OSS_FILE_UPLOAD], true));
  1096. $options[self::OSS_CONTENT_MD5] = $content_md5;
  1097. }
  1098. if (!isset($options[self::OSS_CONTENT_TYPE])) {
  1099. $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object, $file);
  1100. }
  1101. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  1102. $options[self::OSS_BUCKET] = $bucket;
  1103. $options[self::OSS_OBJECT] = $object;
  1104. $options[self::OSS_CONTENT_LENGTH] = $file_size;
  1105. $response = $this->auth($options);
  1106. $result = new PutSetDeleteResult($response);
  1107. return $result->getData();
  1108. }
  1109. /**
  1110. * 追加上传内存中的内容
  1111. *
  1112. * @param string $bucket bucket名称
  1113. * @param string $object objcet名称
  1114. * @param string $content 本次追加上传的内容
  1115. * @param array $options
  1116. * @return int next append position
  1117. * @throws OssException
  1118. */
  1119. public function appendObject($bucket, $object, $content, $position, $options = NULL)
  1120. {
  1121. $this->precheckCommon($bucket, $object, $options);
  1122. $options[self::OSS_CONTENT] = $content;
  1123. $options[self::OSS_BUCKET] = $bucket;
  1124. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  1125. $options[self::OSS_OBJECT] = $object;
  1126. $options[self::OSS_SUB_RESOURCE] = 'append';
  1127. $options[self::OSS_POSITION] = strval($position);
  1128. if (!isset($options[self::OSS_LENGTH])) {
  1129. $options[self::OSS_CONTENT_LENGTH] = strlen($options[self::OSS_CONTENT]);
  1130. } else {
  1131. $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
  1132. }
  1133. $is_check_md5 = $this->isCheckMD5($options);
  1134. if ($is_check_md5) {
  1135. $content_md5 = base64_encode(md5($content, true));
  1136. $options[self::OSS_CONTENT_MD5] = $content_md5;
  1137. }
  1138. if (!isset($options[self::OSS_CONTENT_TYPE])) {
  1139. $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object);
  1140. }
  1141. $response = $this->auth($options);
  1142. $result = new AppendResult($response);
  1143. return $result->getData();
  1144. }
  1145. /**
  1146. * 追加上传本地文件
  1147. *
  1148. * @param string $bucket bucket名称
  1149. * @param string $object object名称
  1150. * @param string $file 追加上传的本地文件路径
  1151. * @param array $options
  1152. * @return int next append position
  1153. * @throws OssException
  1154. */
  1155. public function appendFile($bucket, $object, $file, $position, $options = NULL)
  1156. {
  1157. $this->precheckCommon($bucket, $object, $options);
  1158. OssUtil::throwOssExceptionWithMessageIfEmpty($file, "file path is invalid");
  1159. $file = OssUtil::encodePath($file);
  1160. if (!file_exists($file)) {
  1161. throw new OssException($file . " file does not exist");
  1162. }
  1163. $options[self::OSS_FILE_UPLOAD] = $file;
  1164. $file_size = filesize($options[self::OSS_FILE_UPLOAD]);
  1165. $is_check_md5 = $this->isCheckMD5($options);
  1166. if ($is_check_md5) {
  1167. $content_md5 = base64_encode(md5_file($options[self::OSS_FILE_UPLOAD], true));
  1168. $options[self::OSS_CONTENT_MD5] = $content_md5;
  1169. }
  1170. if (!isset($options[self::OSS_CONTENT_TYPE])) {
  1171. $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object, $file);
  1172. }
  1173. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  1174. $options[self::OSS_BUCKET] = $bucket;
  1175. $options[self::OSS_OBJECT] = $object;
  1176. $options[self::OSS_CONTENT_LENGTH] = $file_size;
  1177. $options[self::OSS_SUB_RESOURCE] = 'append';
  1178. $options[self::OSS_POSITION] = strval($position);
  1179. $response = $this->auth($options);
  1180. $result = new AppendResult($response);
  1181. return $result->getData();
  1182. }
  1183. /**
  1184. * 拷贝一个在OSS上已经存在的object成另外一个object
  1185. *
  1186. * @param string $fromBucket 源bucket名称
  1187. * @param string $fromObject 源object名称
  1188. * @param string $toBucket 目标bucket名称
  1189. * @param string $toObject 目标object名称
  1190. * @param array $options
  1191. * @return null
  1192. * @throws OssException
  1193. */
  1194. public function copyObject($fromBucket, $fromObject, $toBucket, $toObject, $options = NULL)
  1195. {
  1196. $this->precheckCommon($fromBucket, $fromObject, $options);
  1197. $this->precheckCommon($toBucket, $toObject, $options);
  1198. $options[self::OSS_BUCKET] = $toBucket;
  1199. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  1200. $options[self::OSS_OBJECT] = $toObject;
  1201. if (isset($options[self::OSS_HEADERS])) {
  1202. $options[self::OSS_HEADERS][self::OSS_OBJECT_COPY_SOURCE] = '/' . $fromBucket . '/' . $fromObject;
  1203. } else {
  1204. $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_COPY_SOURCE => '/' . $fromBucket . '/' . $fromObject);
  1205. }
  1206. $response = $this->auth($options);
  1207. $result = new CopyObjectResult($response);
  1208. return $result->getData();
  1209. }
  1210. /**
  1211. * 获取Object的Meta信息
  1212. *
  1213. * @param string $bucket bucket名称
  1214. * @param string $object object名称
  1215. * @param string $options 具体参考SDK文档
  1216. * @return array
  1217. */
  1218. public function getObjectMeta($bucket, $object, $options = NULL)
  1219. {
  1220. $this->precheckCommon($bucket, $object, $options);
  1221. $options[self::OSS_BUCKET] = $bucket;
  1222. $options[self::OSS_METHOD] = self::OSS_HTTP_HEAD;
  1223. $options[self::OSS_OBJECT] = $object;
  1224. $response = $this->auth($options);
  1225. $result = new HeaderResult($response);
  1226. return $result->getData();
  1227. }
  1228. /**
  1229. * 删除某个Object
  1230. *
  1231. * @param string $bucket bucket名称
  1232. * @param string $object object名称
  1233. * @param array $options
  1234. * @return null
  1235. */
  1236. public function deleteObject($bucket, $object, $options = NULL)
  1237. {
  1238. $this->precheckCommon($bucket, $object, $options);
  1239. $options[self::OSS_BUCKET] = $bucket;
  1240. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  1241. $options[self::OSS_OBJECT] = $object;
  1242. $response = $this->auth($options);
  1243. $result = new PutSetDeleteResult($response);
  1244. return $result->getData();
  1245. }
  1246. /**
  1247. * 删除同一个Bucket中的多个Object
  1248. *
  1249. * @param string $bucket bucket名称
  1250. * @param array $objects object列表
  1251. * @param array $options
  1252. * @return ResponseCore
  1253. * @throws null
  1254. */
  1255. public function deleteObjects($bucket, $objects, $options = null)
  1256. {
  1257. $this->precheckCommon($bucket, NULL, $options, false);
  1258. if (!is_array($objects) || !$objects) {
  1259. throw new OssException('objects must be array');
  1260. }
  1261. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  1262. $options[self::OSS_BUCKET] = $bucket;
  1263. $options[self::OSS_OBJECT] = '/';
  1264. $options[self::OSS_SUB_RESOURCE] = 'delete';
  1265. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  1266. $quiet = 'false';
  1267. if (isset($options['quiet'])) {
  1268. if (is_bool($options['quiet'])) { //Boolean
  1269. $quiet = $options['quiet'] ? 'true' : 'false';
  1270. } elseif (is_string($options['quiet'])) { // string
  1271. $quiet = ($options['quiet'] === 'true') ? 'true' : 'false';
  1272. }
  1273. }
  1274. $xmlBody = OssUtil::createDeleteObjectsXmlBody($objects, $quiet);
  1275. $options[self::OSS_CONTENT] = $xmlBody;
  1276. $response = $this->auth($options);
  1277. $result = new DeleteObjectsResult($response);
  1278. return $result->getData();
  1279. }
  1280. /**
  1281. * 获得Object内容
  1282. *
  1283. * @param string $bucket bucket名称
  1284. * @param string $object object名称
  1285. * @param array $options 该参数中必须设置ALIOSS::OSS_FILE_DOWNLOAD,ALIOSS::OSS_RANGE可选,可以根据实际情况设置;如果不设置,默认会下载全部内容
  1286. * @return string
  1287. */
  1288. public function getObject($bucket, $object, $options = NULL)
  1289. {
  1290. $this->precheckCommon($bucket, $object, $options);
  1291. $options[self::OSS_BUCKET] = $bucket;
  1292. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  1293. $options[self::OSS_OBJECT] = $object;
  1294. if (isset($options[self::OSS_LAST_MODIFIED])) {
  1295. $options[self::OSS_HEADERS][self::OSS_IF_MODIFIED_SINCE] = $options[self::OSS_LAST_MODIFIED];
  1296. unset($options[self::OSS_LAST_MODIFIED]);
  1297. }
  1298. if (isset($options[self::OSS_ETAG])) {
  1299. $options[self::OSS_HEADERS][self::OSS_IF_NONE_MATCH] = $options[self::OSS_ETAG];
  1300. unset($options[self::OSS_ETAG]);
  1301. }
  1302. if (isset($options[self::OSS_RANGE])) {
  1303. $range = $options[self::OSS_RANGE];
  1304. $options[self::OSS_HEADERS][self::OSS_RANGE] = "bytes=$range";
  1305. unset($options[self::OSS_RANGE]);
  1306. }
  1307. $response = $this->auth($options);
  1308. $result = new BodyResult($response);
  1309. return $result->getData();
  1310. }
  1311. /**
  1312. * 检测Object是否存在
  1313. * 通过获取Object的Meta信息来判断Object是否存在, 用户需要自行解析ResponseCore判断object是否存在
  1314. *
  1315. * @param string $bucket bucket名称
  1316. * @param string $object object名称
  1317. * @param array $options
  1318. * @return bool
  1319. */
  1320. public function doesObjectExist($bucket, $object, $options = NULL)
  1321. {
  1322. $this->precheckCommon($bucket, $object, $options);
  1323. $options[self::OSS_BUCKET] = $bucket;
  1324. $options[self::OSS_METHOD] = self::OSS_HTTP_HEAD;
  1325. $options[self::OSS_OBJECT] = $object;
  1326. $response = $this->auth($options);
  1327. $result = new ExistResult($response);
  1328. return $result->getData();
  1329. }
  1330. /**
  1331. * 针对Archive类型的Object读取
  1332. * 需要使用Restore操作让服务端执行解冻任务
  1333. *
  1334. * @param string $bucket bucket名称
  1335. * @param string $object object名称
  1336. * @return null
  1337. * @throws OssException
  1338. */
  1339. public function restoreObject($bucket, $object, $options = NULL)
  1340. {
  1341. $this->precheckCommon($bucket, $object, $options);
  1342. $options[self::OSS_BUCKET] = $bucket;
  1343. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  1344. $options[self::OSS_OBJECT] = $object;
  1345. $options[self::OSS_SUB_RESOURCE] = self::OSS_RESTORE;
  1346. $response = $this->auth($options);
  1347. $result = new PutSetDeleteResult($response);
  1348. return $result->getData();
  1349. }
  1350. /**
  1351. * 获取分片大小,根据用户提供的part_size,重新计算一个更合理的partsize
  1352. *
  1353. * @param int $partSize
  1354. * @return int
  1355. */
  1356. private function computePartSize($partSize)
  1357. {
  1358. $partSize = (integer)$partSize;
  1359. if ($partSize <= self::OSS_MIN_PART_SIZE) {
  1360. $partSize = self::OSS_MIN_PART_SIZE;
  1361. } elseif ($partSize > self::OSS_MAX_PART_SIZE) {
  1362. $partSize = self::OSS_MAX_PART_SIZE;
  1363. }
  1364. return $partSize;
  1365. }
  1366. /**
  1367. * 计算文件可以分成多少个part,以及每个part的长度以及起始位置
  1368. * 方法必须在 <upload_part()>中调用
  1369. *
  1370. * @param integer $file_size 文件大小
  1371. * @param integer $partSize part大小,默认5M
  1372. * @return array An array 包含 key-value 键值对. Key `seekTo` `length`.
  1373. */
  1374. public function generateMultiuploadParts($file_size, $partSize = 5242880)
  1375. {
  1376. $i = 0;
  1377. $size_count = $file_size;
  1378. $values = array();
  1379. $partSize = $this->computePartSize($partSize);
  1380. while ($size_count > 0) {
  1381. $size_count -= $partSize;
  1382. $values[] = array(
  1383. self::OSS_SEEK_TO => ($partSize * $i),
  1384. self::OSS_LENGTH => (($size_count > 0) ? $partSize : ($size_count + $partSize)),
  1385. );
  1386. $i++;
  1387. }
  1388. return $values;
  1389. }
  1390. /**
  1391. * 初始化multi-part upload
  1392. *
  1393. * @param string $bucket Bucket名称
  1394. * @param string $object Object名称
  1395. * @param array $options Key-Value数组
  1396. * @throws OssException
  1397. * @return string 返回uploadid
  1398. */
  1399. public function initiateMultipartUpload($bucket, $object, $options = NULL)
  1400. {
  1401. $this->precheckCommon($bucket, $object, $options);
  1402. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  1403. $options[self::OSS_BUCKET] = $bucket;
  1404. $options[self::OSS_OBJECT] = $object;
  1405. $options[self::OSS_SUB_RESOURCE] = 'uploads';
  1406. $options[self::OSS_CONTENT] = '';
  1407. if (!isset($options[self::OSS_CONTENT_TYPE])) {
  1408. $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object);
  1409. }
  1410. if (!isset($options[self::OSS_HEADERS])) {
  1411. $options[self::OSS_HEADERS] = array();
  1412. }
  1413. $response = $this->auth($options);
  1414. $result = new InitiateMultipartUploadResult($response);
  1415. return $result->getData();
  1416. }
  1417. /**
  1418. * 分片上传的块上传接口
  1419. *
  1420. * @param string $bucket Bucket名称
  1421. * @param string $object Object名称
  1422. * @param string $uploadId
  1423. * @param array $options Key-Value数组
  1424. * @return string eTag
  1425. * @throws OssException
  1426. */
  1427. public function uploadPart($bucket, $object, $uploadId, $options = null)
  1428. {
  1429. $this->precheckCommon($bucket, $object, $options);
  1430. $this->precheckParam($options, self::OSS_FILE_UPLOAD, __FUNCTION__);
  1431. $this->precheckParam($options, self::OSS_PART_NUM, __FUNCTION__);
  1432. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  1433. $options[self::OSS_BUCKET] = $bucket;
  1434. $options[self::OSS_OBJECT] = $object;
  1435. $options[self::OSS_UPLOAD_ID] = $uploadId;
  1436. if (isset($options[self::OSS_LENGTH])) {
  1437. $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
  1438. }
  1439. $response = $this->auth($options);
  1440. $result = new UploadPartResult($response);
  1441. return $result->getData();
  1442. }
  1443. /**
  1444. * 获取已成功上传的part
  1445. *
  1446. * @param string $bucket Bucket名称
  1447. * @param string $object Object名称
  1448. * @param string $uploadId uploadId
  1449. * @param array $options Key-Value数组
  1450. * @return ListPartsInfo
  1451. * @throws OssException
  1452. */
  1453. public function listParts($bucket, $object, $uploadId, $options = null)
  1454. {
  1455. $this->precheckCommon($bucket, $object, $options);
  1456. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  1457. $options[self::OSS_BUCKET] = $bucket;
  1458. $options[self::OSS_OBJECT] = $object;
  1459. $options[self::OSS_UPLOAD_ID] = $uploadId;
  1460. $options[self::OSS_QUERY_STRING] = array();
  1461. foreach (array('max-parts', 'part-number-marker') as $param) {
  1462. if (isset($options[$param])) {
  1463. $options[self::OSS_QUERY_STRING][$param] = $options[$param];
  1464. unset($options[$param]);
  1465. }
  1466. }
  1467. $response = $this->auth($options);
  1468. $result = new ListPartsResult($response);
  1469. return $result->getData();
  1470. }
  1471. /**
  1472. * 中止进行一半的分片上传操作
  1473. *
  1474. * @param string $bucket Bucket名称
  1475. * @param string $object Object名称
  1476. * @param string $uploadId uploadId
  1477. * @param array $options Key-Value数组
  1478. * @return null
  1479. * @throws OssException
  1480. */
  1481. public function abortMultipartUpload($bucket, $object, $uploadId, $options = NULL)
  1482. {
  1483. $this->precheckCommon($bucket, $object, $options);
  1484. $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
  1485. $options[self::OSS_BUCKET] = $bucket;
  1486. $options[self::OSS_OBJECT] = $object;
  1487. $options[self::OSS_UPLOAD_ID] = $uploadId;
  1488. $response = $this->auth($options);
  1489. $result = new PutSetDeleteResult($response);
  1490. return $result->getData();
  1491. }
  1492. /**
  1493. * 在将所有数据Part都上传完成后,调用此接口完成本次分块上传
  1494. *
  1495. * @param string $bucket Bucket名称
  1496. * @param string $object Object名称
  1497. * @param string $uploadId uploadId
  1498. * @param array $listParts array( array("PartNumber"=> int, "ETag"=>string))
  1499. * @param array $options Key-Value数组
  1500. * @throws OssException
  1501. * @return null
  1502. */
  1503. public function completeMultipartUpload($bucket, $object, $uploadId, $listParts, $options = NULL)
  1504. {
  1505. $this->precheckCommon($bucket, $object, $options);
  1506. $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
  1507. $options[self::OSS_BUCKET] = $bucket;
  1508. $options[self::OSS_OBJECT] = $object;
  1509. $options[self::OSS_UPLOAD_ID] = $uploadId;
  1510. $options[self::OSS_CONTENT_TYPE] = 'application/xml';
  1511. if (!is_array($listParts)) {
  1512. throw new OssException("listParts must be array type");
  1513. }
  1514. $options[self::OSS_CONTENT] = OssUtil::createCompleteMultipartUploadXmlBody($listParts);
  1515. $response = $this->auth($options);
  1516. if (isset($options[self::OSS_CALLBACK]) && !empty($options[self::OSS_CALLBACK])) {
  1517. $result = new CallbackResult($response);
  1518. } else {
  1519. $result = new PutSetDeleteResult($response);
  1520. }
  1521. return $result->getData();
  1522. }
  1523. /**
  1524. * 罗列出所有执行中的Multipart Upload事件,即已经被初始化的Multipart Upload但是未被
  1525. * Complete或者Abort的Multipart Upload事件
  1526. *
  1527. * @param string $bucket bucket
  1528. * @param array $options 关联数组
  1529. * @throws OssException
  1530. * @return ListMultipartUploadInfo
  1531. */
  1532. public function listMultipartUploads($bucket, $options = null)
  1533. {
  1534. $this->precheckCommon($bucket, NULL, $options, false);
  1535. $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
  1536. $options[self::OSS_BUCKET] = $bucket;
  1537. $options[self::OSS_OBJECT] = '/';
  1538. $options[self::OSS_SUB_RESOURCE] = 'uploads';
  1539. foreach (array('delimiter', 'key-marker', 'max-uploads', 'prefix', 'upload-id-marker') as $param) {
  1540. if (isset($options[$param])) {
  1541. $options[self::OSS_QUERY_STRING][$param] = $options[$param];
  1542. unset($options[$param]);
  1543. }
  1544. }
  1545. $query = isset($options[self::OSS_QUERY_STRING]) ? $options[self::OSS_QUERY_STRING] : array();
  1546. $options[self::OSS_QUERY_STRING] = array_merge(
  1547. $query,
  1548. array(self::OSS_ENCODING_TYPE => self::OSS_ENCODING_TYPE_URL)
  1549. );
  1550. $response = $this->auth($options);
  1551. $result = new ListMultipartUploadResult($response);
  1552. return $result->getData();
  1553. }
  1554. /**
  1555. * 从一个已存在的Object中拷贝数据来上传一个Part
  1556. *
  1557. * @param string $fromBucket 源bucket名称
  1558. * @param string $fromObject 源object名称
  1559. * @param string $toBucket 目标bucket名称
  1560. * @param string $toObject 目标object名称
  1561. * @param int $partNumber 分块上传的块id
  1562. * @param string $uploadId 初始化multipart upload返回的uploadid
  1563. * @param array $options Key-Value数组
  1564. * @return null
  1565. * @throws OssException
  1566. */
  1567. public function uploadPartCopy($fromBucket, $fromObject, $toBucket, $toObject, $partNumber, $uploadId, $options = NULL)
  1568. {
  1569. $this->precheckCommon($fromBucket, $fromObject, $options);
  1570. $this->precheckCommon($toBucket, $toObject, $options);
  1571. //如果没有设置$options['isFullCopy'],则需要强制判断copy的起止位置
  1572. $start_range = "0";
  1573. if (isset($options['start'])) {
  1574. $start_range = $options['start'];
  1575. }
  1576. $end_range = "";
  1577. if (isset($options['end'])) {
  1578. $end_range = $options['end'];
  1579. }
  1580. $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
  1581. $options[self::OSS_BUCKET] = $toBucket;
  1582. $options[self::OSS_OBJECT] = $toObject;
  1583. $options[self::OSS_PART_NUM] = $partNumber;
  1584. $options[self::OSS_UPLOAD_ID] = $uploadId;
  1585. if (!isset($options[self::OSS_HEADERS])) {
  1586. $options[self::OSS_HEADERS] = array();
  1587. }
  1588. $options[self::OSS_HEADERS][self::OSS_OBJECT_COPY_SOURCE] = '/' . $fromBucket . '/' . $fromObject;
  1589. $options[self::OSS_HEADERS][self::OSS_OBJECT_COPY_SOURCE_RANGE] = "bytes=" . $start_range . "-" . $end_range;
  1590. $response = $this->auth($options);
  1591. $result = new UploadPartResult($response);
  1592. return $result->getData();
  1593. }
  1594. /**
  1595. * multipart上传统一封装,从初始化到完成multipart,以及出错后中止动作
  1596. *
  1597. * @param string $bucket bucket名称
  1598. * @param string $object object名称
  1599. * @param string $file 需要上传的本地文件的路径
  1600. * @param array $options Key-Value数组
  1601. * @return null
  1602. * @throws OssException
  1603. */
  1604. public function multiuploadFile($bucket, $object, $file, $options = null)
  1605. {
  1606. $this->precheckCommon($bucket, $object, $options);
  1607. if (isset($options[self::OSS_LENGTH])) {
  1608. $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
  1609. unset($options[self::OSS_LENGTH]);
  1610. }
  1611. if (empty($file)) {
  1612. throw new OssException("parameter invalid, file is empty");
  1613. }
  1614. $uploadFile = OssUtil::encodePath($file);
  1615. if (!isset($options[self::OSS_CONTENT_TYPE])) {
  1616. $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object, $uploadFile);
  1617. }
  1618. $upload_position = isset($options[self::OSS_SEEK_TO]) ? (integer)$options[self::OSS_SEEK_TO] : 0;
  1619. if (isset($options[self::OSS_CONTENT_LENGTH])) {
  1620. $upload_file_size = (integer)$options[self::OSS_CONTENT_LENGTH];
  1621. } else {
  1622. $upload_file_size = filesize($uploadFile);
  1623. if ($upload_file_size !== false) {
  1624. $upload_file_size -= $upload_position;
  1625. }
  1626. }
  1627. if ($upload_position === false || !isset($upload_file_size) || $upload_file_size === false || $upload_file_size < 0) {
  1628. throw new OssException('The size of `fileUpload` cannot be determined in ' . __FUNCTION__ . '().');
  1629. }
  1630. // 处理partSize
  1631. if (isset($options[self::OSS_PART_SIZE])) {
  1632. $options[self::OSS_PART_SIZE] = $this->computePartSize($options[self::OSS_PART_SIZE]);
  1633. } else {
  1634. $options[self::OSS_PART_SIZE] = self::OSS_MID_PART_SIZE;
  1635. }
  1636. $is_check_md5 = $this->isCheckMD5($options);
  1637. // 如果上传的文件小于partSize,则直接使用普通方式上传
  1638. if ($upload_file_size < $options[self::OSS_PART_SIZE] && !isset($options[self::OSS_UPLOAD_ID])) {
  1639. return $this->uploadFile($bucket, $object, $uploadFile, $options);
  1640. }
  1641. // 初始化multipart
  1642. if (isset($options[self::OSS_UPLOAD_ID])) {
  1643. $uploadId = $options[self::OSS_UPLOAD_ID];
  1644. } else {
  1645. // 初始化
  1646. $uploadId = $this->initiateMultipartUpload($bucket, $object, $options);
  1647. }
  1648. // 获取的分片
  1649. $pieces = $this->generateMultiuploadParts($upload_file_size, (integer)$options[self::OSS_PART_SIZE]);
  1650. $response_upload_part = array();
  1651. foreach ($pieces as $i => $piece) {
  1652. $from_pos = $upload_position + (integer)$piece[self::OSS_SEEK_TO];
  1653. $to_pos = (integer)$piece[self::OSS_LENGTH] + $from_pos - 1;
  1654. $up_options = array(
  1655. self::OSS_FILE_UPLOAD => $uploadFile,
  1656. self::OSS_PART_NUM => ($i + 1),
  1657. self::OSS_SEEK_TO => $from_pos,
  1658. self::OSS_LENGTH => $to_pos - $from_pos + 1,
  1659. self::OSS_CHECK_MD5 => $is_check_md5,
  1660. );
  1661. if ($is_check_md5) {
  1662. $content_md5 = OssUtil::getMd5SumForFile($uploadFile, $from_pos, $to_pos);
  1663. $up_options[self::OSS_CONTENT_MD5] = $content_md5;
  1664. }
  1665. $response_upload_part[] = $this->uploadPart($bucket, $object, $uploadId, $up_options);
  1666. }
  1667. $uploadParts = array();
  1668. foreach ($response_upload_part as $i => $etag) {
  1669. $uploadParts[] = array(
  1670. 'PartNumber' => ($i + 1),
  1671. 'ETag' => $etag,
  1672. );
  1673. }
  1674. return $this->completeMultipartUpload($bucket, $object, $uploadId, $uploadParts);
  1675. }
  1676. /**
  1677. * 上传本地目录内的文件或者目录到指定bucket的指定prefix的object中
  1678. *
  1679. * @param string $bucket bucket名称
  1680. * @param string $prefix 需要上传到的object的key前缀,可以理解成bucket中的子目录,结尾不能是'/',接口中会补充'/'
  1681. * @param string $localDirectory 需要上传的本地目录
  1682. * @param string $exclude 需要排除的目录
  1683. * @param bool $recursive 是否递归的上传localDirectory下的子目录内容
  1684. * @param bool $checkMd5
  1685. * @return array 返回两个列表 array("succeededList" => array("object"), "failedList" => array("object"=>"errorMessage"))
  1686. * @throws OssException
  1687. */
  1688. public function uploadDir($bucket, $prefix, $localDirectory, $exclude = '.|..|.svn|.git', $recursive = false, $checkMd5 = true)
  1689. {
  1690. $retArray = array("succeededList" => array(), "failedList" => array());
  1691. if (empty($bucket)) throw new OssException("parameter error, bucket is empty");
  1692. if (!is_string($prefix)) throw new OssException("parameter error, prefix is not string");
  1693. if (empty($localDirectory)) throw new OssException("parameter error, localDirectory is empty");
  1694. $directory = $localDirectory;
  1695. $directory = OssUtil::encodePath($directory);
  1696. //判断是否目录
  1697. if (!is_dir($directory)) {
  1698. throw new OssException('parameter error: ' . $directory . ' is not a directory, please check it');
  1699. }
  1700. //read directory
  1701. $file_list_array = OssUtil::readDir($directory, $exclude, $recursive);
  1702. if (!$file_list_array) {
  1703. throw new OssException($directory . ' is empty...');
  1704. }
  1705. foreach ($file_list_array as $k => $item) {
  1706. if (is_dir($item['path'])) {
  1707. continue;
  1708. }
  1709. $options = array(
  1710. self::OSS_PART_SIZE => self::OSS_MIN_PART_SIZE,
  1711. self::OSS_CHECK_MD5 => $checkMd5,
  1712. );
  1713. $realObject = (!empty($prefix) ? $prefix . '/' : '') . $item['file'];
  1714. try {
  1715. $this->multiuploadFile($bucket, $realObject, $item['path'], $options);
  1716. $retArray["succeededList"][] = $realObject;
  1717. } catch (OssException $e) {
  1718. $retArray["failedList"][$realObject] = $e->getMessage();
  1719. }
  1720. }
  1721. return $retArray;
  1722. }
  1723. /**
  1724. * 支持生成get和put签名, 用户可以生成一个具有一定有效期的
  1725. * 签名过的url
  1726. *
  1727. * @param string $bucket
  1728. * @param string $object
  1729. * @param int $timeout
  1730. * @param string $method
  1731. * @param array $options Key-Value数组
  1732. * @return string
  1733. * @throws OssException
  1734. */
  1735. public function signUrl($bucket, $object, $timeout = 60, $method = self::OSS_HTTP_GET, $options = NULL)
  1736. {
  1737. $this->precheckCommon($bucket, $object, $options);
  1738. //method
  1739. if (self::OSS_HTTP_GET !== $method && self::OSS_HTTP_PUT !== $method) {
  1740. throw new OssException("method is invalid");
  1741. }
  1742. $options[self::OSS_BUCKET] = $bucket;
  1743. $options[self::OSS_OBJECT] = $object;
  1744. $options[self::OSS_METHOD] = $method;
  1745. if (!isset($options[self::OSS_CONTENT_TYPE])) {
  1746. $options[self::OSS_CONTENT_TYPE] = '';
  1747. }
  1748. $timeout = time() + $timeout;
  1749. $options[self::OSS_PREAUTH] = $timeout;
  1750. $options[self::OSS_DATE] = $timeout;
  1751. $this->setSignStsInUrl(true);
  1752. return $this->auth($options);
  1753. }
  1754. /**
  1755. * 检测options参数
  1756. *
  1757. * @param array $options
  1758. * @throws OssException
  1759. */
  1760. private function precheckOptions(&$options)
  1761. {
  1762. OssUtil::validateOptions($options);
  1763. if (!$options) {
  1764. $options = array();
  1765. }
  1766. }
  1767. /**
  1768. * 校验bucket参数
  1769. *
  1770. * @param string $bucket
  1771. * @param string $errMsg
  1772. * @throws OssException
  1773. */
  1774. private function precheckBucket($bucket, $errMsg = 'bucket is not allowed empty')
  1775. {
  1776. OssUtil::throwOssExceptionWithMessageIfEmpty($bucket, $errMsg);
  1777. }
  1778. /**
  1779. * 校验object参数
  1780. *
  1781. * @param string $object
  1782. * @throws OssException
  1783. */
  1784. private function precheckObject($object)
  1785. {
  1786. OssUtil::throwOssExceptionWithMessageIfEmpty($object, "object name is empty");
  1787. }
  1788. /**
  1789. * 校验option restore
  1790. *
  1791. * @param string $restore
  1792. * @throws OssException
  1793. */
  1794. private function precheckStorage($storage)
  1795. {
  1796. if (is_string($storage)) {
  1797. switch ($storage) {
  1798. case self::OSS_STORAGE_ARCHIVE:
  1799. return;
  1800. case self::OSS_STORAGE_IA:
  1801. return;
  1802. case self::OSS_STORAGE_STANDARD:
  1803. return;
  1804. default:
  1805. break;
  1806. }
  1807. }
  1808. throw new OssException('storage name is invalid');
  1809. }
  1810. /**
  1811. * 校验bucket,options参数
  1812. *
  1813. * @param string $bucket
  1814. * @param string $object
  1815. * @param array $options
  1816. * @param bool $isCheckObject
  1817. */
  1818. private function precheckCommon($bucket, $object, &$options, $isCheckObject = true)
  1819. {
  1820. if ($isCheckObject) {
  1821. $this->precheckObject($object);
  1822. }
  1823. $this->precheckOptions($options);
  1824. $this->precheckBucket($bucket);
  1825. }
  1826. /**
  1827. * 参数校验
  1828. *
  1829. * @param array $options
  1830. * @param string $param
  1831. * @param string $funcName
  1832. * @throws OssException
  1833. */
  1834. private function precheckParam($options, $param, $funcName)
  1835. {
  1836. if (!isset($options[$param])) {
  1837. throw new OssException('The `' . $param . '` options is required in ' . $funcName . '().');
  1838. }
  1839. }
  1840. /**
  1841. * 检测md5
  1842. *
  1843. * @param array $options
  1844. * @return bool|null
  1845. */
  1846. private function isCheckMD5($options)
  1847. {
  1848. return $this->getValue($options, self::OSS_CHECK_MD5, false, true, true);
  1849. }
  1850. /**
  1851. * 获取value
  1852. *
  1853. * @param array $options
  1854. * @param string $key
  1855. * @param string $default
  1856. * @param bool $isCheckEmpty
  1857. * @param bool $isCheckBool
  1858. * @return bool|null
  1859. */
  1860. private function getValue($options, $key, $default = NULL, $isCheckEmpty = false, $isCheckBool = false)
  1861. {
  1862. $value = $default;
  1863. if (isset($options[$key])) {
  1864. if ($isCheckEmpty) {
  1865. if (!empty($options[$key])) {
  1866. $value = $options[$key];
  1867. }
  1868. } else {
  1869. $value = $options[$key];
  1870. }
  1871. unset($options[$key]);
  1872. }
  1873. if ($isCheckBool) {
  1874. if ($value !== true && $value !== false) {
  1875. $value = false;
  1876. }
  1877. }
  1878. return $value;
  1879. }
  1880. /**
  1881. * 获取mimetype类型
  1882. *
  1883. * @param string $object
  1884. * @return string
  1885. */
  1886. private function getMimeType($object, $file = null)
  1887. {
  1888. if (!is_null($file)) {
  1889. $type = MimeTypes::getMimetype($file);
  1890. if (!is_null($type)) {
  1891. return $type;
  1892. }
  1893. }
  1894. $type = MimeTypes::getMimetype($object);
  1895. if (!is_null($type)) {
  1896. return $type;
  1897. }
  1898. return self::DEFAULT_CONTENT_TYPE;
  1899. }
  1900. /**
  1901. * 验证并且执行请求,按照OSS Api协议,执行操作
  1902. *
  1903. * @param array $options
  1904. * @return ResponseCore
  1905. * @throws OssException
  1906. * @throws RequestCore_Exception
  1907. */
  1908. private function auth($options)
  1909. {
  1910. OssUtil::validateOptions($options);
  1911. //验证bucket,list_bucket时不需要验证
  1912. $this->authPrecheckBucket($options);
  1913. //验证object
  1914. $this->authPrecheckObject($options);
  1915. //Object名称的编码必须是utf8
  1916. $this->authPrecheckObjectEncoding($options);
  1917. //验证ACL
  1918. $this->authPrecheckAcl($options);
  1919. // 获得当次请求使用的协议头,是https还是http
  1920. $scheme = $this->useSSL ? 'https://' : 'http://';
  1921. // 获得当次请求使用的hostname,如果是公共域名或者专有域名,bucket拼在前面构成三级域名
  1922. $hostname = $this->generateHostname($options[self::OSS_BUCKET]);
  1923. $string_to_sign = '';
  1924. $headers = $this->generateHeaders($options, $hostname);
  1925. $signable_query_string_params = $this->generateSignableQueryStringParam($options);
  1926. $signable_query_string = OssUtil::toQueryString($signable_query_string_params);
  1927. $resource_uri = $this->generateResourceUri($options);
  1928. //生成请求URL
  1929. $conjunction = '?';
  1930. $non_signable_resource = '';
  1931. if (isset($options[self::OSS_SUB_RESOURCE])) {
  1932. $conjunction = '&';
  1933. }
  1934. if ($signable_query_string !== '') {
  1935. $signable_query_string = $conjunction . $signable_query_string;
  1936. $conjunction = '&';
  1937. }
  1938. $query_string = $this->generateQueryString($options);
  1939. if ($query_string !== '') {
  1940. $non_signable_resource .= $conjunction . $query_string;
  1941. $conjunction = '&';
  1942. }
  1943. $this->requestUrl = $scheme . $hostname . $resource_uri . $signable_query_string . $non_signable_resource;
  1944. //创建请求
  1945. $request = new RequestCore($this->requestUrl, $this->requestProxy);
  1946. $request->set_useragent($this->generateUserAgent());
  1947. // Streaming uploads
  1948. if (isset($options[self::OSS_FILE_UPLOAD])) {
  1949. if (is_resource($options[self::OSS_FILE_UPLOAD])) {
  1950. $length = null;
  1951. if (isset($options[self::OSS_CONTENT_LENGTH])) {
  1952. $length = $options[self::OSS_CONTENT_LENGTH];
  1953. } elseif (isset($options[self::OSS_SEEK_TO])) {
  1954. $stats = fstat($options[self::OSS_FILE_UPLOAD]);
  1955. if ($stats && $stats[self::OSS_SIZE] >= 0) {
  1956. $length = $stats[self::OSS_SIZE] - (integer)$options[self::OSS_SEEK_TO];
  1957. }
  1958. }
  1959. $request->set_read_stream($options[self::OSS_FILE_UPLOAD], $length);
  1960. } else {
  1961. $request->set_read_file($options[self::OSS_FILE_UPLOAD]);
  1962. $length = $request->read_stream_size;
  1963. if (isset($options[self::OSS_CONTENT_LENGTH])) {
  1964. $length = $options[self::OSS_CONTENT_LENGTH];
  1965. } elseif (isset($options[self::OSS_SEEK_TO]) && isset($length)) {
  1966. $length -= (integer)$options[self::OSS_SEEK_TO];
  1967. }
  1968. $request->set_read_stream_size($length);
  1969. }
  1970. }
  1971. if (isset($options[self::OSS_SEEK_TO])) {
  1972. $request->set_seek_position((integer)$options[self::OSS_SEEK_TO]);
  1973. }
  1974. if (isset($options[self::OSS_FILE_DOWNLOAD])) {
  1975. if (is_resource($options[self::OSS_FILE_DOWNLOAD])) {
  1976. $request->set_write_stream($options[self::OSS_FILE_DOWNLOAD]);
  1977. } else {
  1978. $request->set_write_file($options[self::OSS_FILE_DOWNLOAD]);
  1979. }
  1980. }
  1981. if (isset($options[self::OSS_METHOD])) {
  1982. $request->set_method($options[self::OSS_METHOD]);
  1983. $string_to_sign .= $options[self::OSS_METHOD] . "\n";
  1984. }
  1985. if (isset($options[self::OSS_CONTENT])) {
  1986. $request->set_body($options[self::OSS_CONTENT]);
  1987. if ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded') {
  1988. $headers[self::OSS_CONTENT_TYPE] = 'application/octet-stream';
  1989. }
  1990. $headers[self::OSS_CONTENT_LENGTH] = strlen($options[self::OSS_CONTENT]);
  1991. $headers[self::OSS_CONTENT_MD5] = base64_encode(md5($options[self::OSS_CONTENT], true));
  1992. }
  1993. if (isset($options[self::OSS_CALLBACK])) {
  1994. $headers[self::OSS_CALLBACK] = base64_encode($options[self::OSS_CALLBACK]);
  1995. }
  1996. if (isset($options[self::OSS_CALLBACK_VAR])) {
  1997. $headers[self::OSS_CALLBACK_VAR] = base64_encode($options[self::OSS_CALLBACK_VAR]);
  1998. }
  1999. if (!isset($headers[self::OSS_ACCEPT_ENCODING])) {
  2000. $headers[self::OSS_ACCEPT_ENCODING] = '';
  2001. }
  2002. uksort($headers, 'strnatcasecmp');
  2003. foreach ($headers as $header_key => $header_value) {
  2004. $header_value = str_replace(array("\r", "\n"), '', $header_value);
  2005. if ($header_value !== '' || $header_key === self::OSS_ACCEPT_ENCODING) {
  2006. $request->add_header($header_key, $header_value);
  2007. }
  2008. if (
  2009. strtolower($header_key) === 'content-md5' ||
  2010. strtolower($header_key) === 'content-type' ||
  2011. strtolower($header_key) === 'date' ||
  2012. (isset($options['self::OSS_PREAUTH']) && (integer)$options['self::OSS_PREAUTH'] > 0)
  2013. ) {
  2014. $string_to_sign .= $header_value . "\n";
  2015. } elseif (substr(strtolower($header_key), 0, 6) === self::OSS_DEFAULT_PREFIX) {
  2016. $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
  2017. }
  2018. }
  2019. // 生成 signable_resource
  2020. $signable_resource = $this->generateSignableResource($options);
  2021. $string_to_sign .= rawurldecode($signable_resource) . urldecode($signable_query_string);
  2022. //对?后面的要签名的string字母序排序
  2023. $string_to_sign_ordered = $this->stringToSignSorted($string_to_sign);
  2024. $signature = base64_encode(hash_hmac('sha1', $string_to_sign_ordered, $this->accessKeySecret, true));
  2025. $request->add_header('Authorization', 'OSS ' . $this->accessKeyId . ':' . $signature);
  2026. if (isset($options[self::OSS_PREAUTH]) && (integer)$options[self::OSS_PREAUTH] > 0) {
  2027. $signed_url = $this->requestUrl . $conjunction . self::OSS_URL_ACCESS_KEY_ID . '=' . rawurlencode($this->accessKeyId) . '&' . self::OSS_URL_EXPIRES . '=' . $options[self::OSS_PREAUTH] . '&' . self::OSS_URL_SIGNATURE . '=' . rawurlencode($signature);
  2028. return $signed_url;
  2029. } elseif (isset($options[self::OSS_PREAUTH])) {
  2030. return $this->requestUrl;
  2031. }
  2032. if ($this->timeout !== 0) {
  2033. $request->timeout = $this->timeout;
  2034. }
  2035. if ($this->connectTimeout !== 0) {
  2036. $request->connect_timeout = $this->connectTimeout;
  2037. }
  2038. try {
  2039. $request->send_request();
  2040. } catch (RequestCore_Exception $e) {
  2041. throw(new OssException('RequestCoreException: ' . $e->getMessage()));
  2042. }
  2043. $response_header = $request->get_response_header();
  2044. $response_header['oss-request-url'] = $this->requestUrl;
  2045. $response_header['oss-redirects'] = $this->redirects;
  2046. $response_header['oss-stringtosign'] = $string_to_sign;
  2047. $response_header['oss-requestheaders'] = $request->request_headers;
  2048. $data = new ResponseCore($response_header, $request->get_response_body(), $request->get_response_code());
  2049. //retry if OSS Internal Error
  2050. if ((integer)$request->get_response_code() === 500) {
  2051. if ($this->redirects <= $this->maxRetries) {
  2052. //设置休眠
  2053. $delay = (integer)(pow(4, $this->redirects) * 100000);
  2054. usleep($delay);
  2055. $this->redirects++;
  2056. $data = $this->auth($options);
  2057. }
  2058. }
  2059. $this->redirects = 0;
  2060. return $data;
  2061. }
  2062. /**
  2063. * 设置最大尝试次数
  2064. *
  2065. * @param int $maxRetries
  2066. * @return void
  2067. */
  2068. public function setMaxTries($maxRetries = 3)
  2069. {
  2070. $this->maxRetries = $maxRetries;
  2071. }
  2072. /**
  2073. * 获取最大尝试次数
  2074. *
  2075. * @return int
  2076. */
  2077. public function getMaxRetries()
  2078. {
  2079. return $this->maxRetries;
  2080. }
  2081. /**
  2082. * 打开sts enable标志,使用户构造函数中传入的$sts生效
  2083. *
  2084. * @param boolean $enable
  2085. */
  2086. public function setSignStsInUrl($enable)
  2087. {
  2088. $this->enableStsInUrl = $enable;
  2089. }
  2090. /**
  2091. * @return boolean
  2092. */
  2093. public function isUseSSL()
  2094. {
  2095. return $this->useSSL;
  2096. }
  2097. /**
  2098. * @param boolean $useSSL
  2099. */
  2100. public function setUseSSL($useSSL)
  2101. {
  2102. $this->useSSL = $useSSL;
  2103. }
  2104. /**
  2105. * 检查bucket名称格式是否正确,如果非法抛出异常
  2106. *
  2107. * @param $options
  2108. * @throws OssException
  2109. */
  2110. private function authPrecheckBucket($options)
  2111. {
  2112. if (!(('/' == $options[self::OSS_OBJECT]) && ('' == $options[self::OSS_BUCKET]) && ('GET' == $options[self::OSS_METHOD])) && !OssUtil::validateBucket($options[self::OSS_BUCKET])) {
  2113. throw new OssException('"' . $options[self::OSS_BUCKET] . '"' . 'bucket name is invalid');
  2114. }
  2115. }
  2116. /**
  2117. *
  2118. * 检查object名称格式是否正确,如果非法抛出异常
  2119. *
  2120. * @param $options
  2121. * @throws OssException
  2122. */
  2123. private function authPrecheckObject($options)
  2124. {
  2125. if (isset($options[self::OSS_OBJECT]) && $options[self::OSS_OBJECT] === '/') {
  2126. return;
  2127. }
  2128. if (isset($options[self::OSS_OBJECT]) && !OssUtil::validateObject($options[self::OSS_OBJECT])) {
  2129. throw new OssException('"' . $options[self::OSS_OBJECT] . '"' . ' object name is invalid');
  2130. }
  2131. }
  2132. /**
  2133. * 检查object的编码,如果是gbk或者gb2312则尝试将其转化为utf8编码
  2134. *
  2135. * @param mixed $options 参数
  2136. */
  2137. private function authPrecheckObjectEncoding(&$options)
  2138. {
  2139. $tmp_object = $options[self::OSS_OBJECT];
  2140. try {
  2141. if (OssUtil::isGb2312($options[self::OSS_OBJECT])) {
  2142. $options[self::OSS_OBJECT] = iconv('GB2312', "UTF-8//IGNORE", $options[self::OSS_OBJECT]);
  2143. } elseif (OssUtil::checkChar($options[self::OSS_OBJECT], true)) {
  2144. $options[self::OSS_OBJECT] = iconv('GBK', "UTF-8//IGNORE", $options[self::OSS_OBJECT]);
  2145. }
  2146. } catch (\Exception $e) {
  2147. try {
  2148. $tmp_object = iconv(mb_detect_encoding($tmp_object), "UTF-8", $tmp_object);
  2149. } catch (\Exception $e) {
  2150. }
  2151. }
  2152. $options[self::OSS_OBJECT] = $tmp_object;
  2153. }
  2154. /**
  2155. * 检查ACL是否是预定义中三种之一,如果不是抛出异常
  2156. *
  2157. * @param $options
  2158. * @throws OssException
  2159. */
  2160. private function authPrecheckAcl($options)
  2161. {
  2162. if (isset($options[self::OSS_HEADERS][self::OSS_ACL]) && !empty($options[self::OSS_HEADERS][self::OSS_ACL])) {
  2163. if (!in_array(strtolower($options[self::OSS_HEADERS][self::OSS_ACL]), self::$OSS_ACL_TYPES)) {
  2164. throw new OssException($options[self::OSS_HEADERS][self::OSS_ACL] . ':' . 'acl is invalid(private,public-read,public-read-write)');
  2165. }
  2166. }
  2167. }
  2168. /**
  2169. * 获得档次请求使用的域名
  2170. * bucket在前的三级域名,或者二级域名,如果是cname或者ip的话,则是二级域名
  2171. *
  2172. * @param $bucket
  2173. * @return string 剥掉协议头的域名
  2174. */
  2175. private function generateHostname($bucket)
  2176. {
  2177. if ($this->hostType === self::OSS_HOST_TYPE_IP) {
  2178. $hostname = $this->hostname;
  2179. } elseif ($this->hostType === self::OSS_HOST_TYPE_CNAME) {
  2180. $hostname = $this->hostname;
  2181. } else {
  2182. // 专有域或者官网endpoint
  2183. $hostname = ($bucket == '') ? $this->hostname : ($bucket . '.') . $this->hostname;
  2184. }
  2185. return $hostname;
  2186. }
  2187. /**
  2188. * 获得当次请求的资源定位字段
  2189. *
  2190. * @param $options
  2191. * @return string 资源定位字段
  2192. */
  2193. private function generateResourceUri($options)
  2194. {
  2195. $resource_uri = "";
  2196. // resource_uri + bucket
  2197. if (isset($options[self::OSS_BUCKET]) && '' !== $options[self::OSS_BUCKET]) {
  2198. if ($this->hostType === self::OSS_HOST_TYPE_IP) {
  2199. $resource_uri = '/' . $options[self::OSS_BUCKET];
  2200. }
  2201. }
  2202. // resource_uri + object
  2203. if (isset($options[self::OSS_OBJECT]) && '/' !== $options[self::OSS_OBJECT]) {
  2204. $resource_uri .= '/' . str_replace(array('%2F', '%25'), array('/', '%'), rawurlencode($options[self::OSS_OBJECT]));
  2205. }
  2206. // resource_uri + sub_resource
  2207. $conjunction = '?';
  2208. if (isset($options[self::OSS_SUB_RESOURCE])) {
  2209. $resource_uri .= $conjunction . $options[self::OSS_SUB_RESOURCE];
  2210. }
  2211. return $resource_uri;
  2212. }
  2213. /**
  2214. * 生成signalbe_query_string_param, array类型
  2215. *
  2216. * @param array $options
  2217. * @return array
  2218. */
  2219. private function generateSignableQueryStringParam($options)
  2220. {
  2221. $signableQueryStringParams = array();
  2222. $signableList = array(
  2223. self::OSS_PART_NUM,
  2224. 'response-content-type',
  2225. 'response-content-language',
  2226. 'response-cache-control',
  2227. 'response-content-encoding',
  2228. 'response-expires',
  2229. 'response-content-disposition',
  2230. self::OSS_UPLOAD_ID,
  2231. self::OSS_COMP,
  2232. self::OSS_LIVE_CHANNEL_STATUS,
  2233. self::OSS_LIVE_CHANNEL_START_TIME,
  2234. self::OSS_LIVE_CHANNEL_END_TIME,
  2235. self::OSS_PROCESS,
  2236. self::OSS_POSITION,
  2237. self::OSS_SYMLINK,
  2238. self::OSS_RESTORE,
  2239. );
  2240. foreach ($signableList as $item) {
  2241. if (isset($options[$item])) {
  2242. $signableQueryStringParams[$item] = $options[$item];
  2243. }
  2244. }
  2245. if ($this->enableStsInUrl && (!is_null($this->securityToken))) {
  2246. $signableQueryStringParams["security-token"] = $this->securityToken;
  2247. }
  2248. return $signableQueryStringParams;
  2249. }
  2250. /**
  2251. * 生成用于签名resource段
  2252. *
  2253. * @param mixed $options
  2254. * @return string
  2255. */
  2256. private function generateSignableResource($options)
  2257. {
  2258. $signableResource = "";
  2259. $signableResource .= '/';
  2260. if (isset($options[self::OSS_BUCKET]) && '' !== $options[self::OSS_BUCKET]) {
  2261. $signableResource .= $options[self::OSS_BUCKET];
  2262. // 如果操作没有Object操作的话,这里最后是否有斜线有个trick,ip的域名下,不需要加'/', 否则需要加'/'
  2263. if ($options[self::OSS_OBJECT] == '/') {
  2264. if ($this->hostType !== self::OSS_HOST_TYPE_IP) {
  2265. $signableResource .= "/";
  2266. }
  2267. }
  2268. }
  2269. //signable_resource + object
  2270. if (isset($options[self::OSS_OBJECT]) && '/' !== $options[self::OSS_OBJECT]) {
  2271. $signableResource .= '/' . str_replace(array('%2F', '%25'), array('/', '%'), rawurlencode($options[self::OSS_OBJECT]));
  2272. }
  2273. if (isset($options[self::OSS_SUB_RESOURCE])) {
  2274. $signableResource .= '?' . $options[self::OSS_SUB_RESOURCE];
  2275. }
  2276. return $signableResource;
  2277. }
  2278. /**
  2279. * 生成query_string
  2280. *
  2281. * @param mixed $options
  2282. * @return string
  2283. */
  2284. private function generateQueryString($options)
  2285. {
  2286. //请求参数
  2287. $queryStringParams = array();
  2288. if (isset($options[self::OSS_QUERY_STRING])) {
  2289. $queryStringParams = array_merge($queryStringParams, $options[self::OSS_QUERY_STRING]);
  2290. }
  2291. return OssUtil::toQueryString($queryStringParams);
  2292. }
  2293. private function stringToSignSorted($string_to_sign)
  2294. {
  2295. $queryStringSorted = '';
  2296. $explodeResult = explode('?', $string_to_sign);
  2297. $index = count($explodeResult);
  2298. if ($index === 1)
  2299. return $string_to_sign;
  2300. $queryStringParams = explode('&', $explodeResult[$index - 1]);
  2301. sort($queryStringParams);
  2302. foreach($queryStringParams as $params)
  2303. {
  2304. $queryStringSorted .= $params . '&';
  2305. }
  2306. $queryStringSorted = substr($queryStringSorted, 0, -1);
  2307. return $explodeResult[0] . '?' . $queryStringSorted;
  2308. }
  2309. /**
  2310. * 初始化headers
  2311. *
  2312. * @param mixed $options
  2313. * @param string $hostname hostname
  2314. * @return array
  2315. */
  2316. private function generateHeaders($options, $hostname)
  2317. {
  2318. $headers = array(
  2319. self::OSS_CONTENT_MD5 => '',
  2320. self::OSS_CONTENT_TYPE => isset($options[self::OSS_CONTENT_TYPE]) ? $options[self::OSS_CONTENT_TYPE] : self::DEFAULT_CONTENT_TYPE,
  2321. self::OSS_DATE => isset($options[self::OSS_DATE]) ? $options[self::OSS_DATE] : gmdate('D, d M Y H:i:s \G\M\T'),
  2322. self::OSS_HOST => $hostname,
  2323. );
  2324. if (isset($options[self::OSS_CONTENT_MD5])) {
  2325. $headers[self::OSS_CONTENT_MD5] = $options[self::OSS_CONTENT_MD5];
  2326. }
  2327. //添加stsSecurityToken
  2328. if ((!is_null($this->securityToken)) && (!$this->enableStsInUrl)) {
  2329. $headers[self::OSS_SECURITY_TOKEN] = $this->securityToken;
  2330. }
  2331. //合并HTTP headers
  2332. if (isset($options[self::OSS_HEADERS])) {
  2333. $headers = array_merge($headers, $options[self::OSS_HEADERS]);
  2334. }
  2335. return $headers;
  2336. }
  2337. /**
  2338. * 生成请求用的UserAgent
  2339. *
  2340. * @return string
  2341. */
  2342. private function generateUserAgent()
  2343. {
  2344. return self::OSS_NAME . "/" . self::OSS_VERSION . " (" . php_uname('s') . "/" . php_uname('r') . "/" . php_uname('m') . ";" . PHP_VERSION . ")";
  2345. }
  2346. /**
  2347. * 检查endpoint的种类
  2348. * 如有有协议头,剥去协议头
  2349. * 并且根据参数 is_cname 和endpoint本身,判定域名类型,是ip,cname,还是专有域或者官网域名
  2350. *
  2351. * @param string $endpoint
  2352. * @param boolean $isCName
  2353. * @return string 剥掉协议头的域名
  2354. */
  2355. private function checkEndpoint($endpoint, $isCName)
  2356. {
  2357. $ret_endpoint = null;
  2358. if (strpos($endpoint, 'http://') === 0) {
  2359. $ret_endpoint = substr($endpoint, strlen('http://'));
  2360. } elseif (strpos($endpoint, 'https://') === 0) {
  2361. $ret_endpoint = substr($endpoint, strlen('https://'));
  2362. $this->useSSL = true;
  2363. } else {
  2364. $ret_endpoint = $endpoint;
  2365. }
  2366. if ($isCName) {
  2367. $this->hostType = self::OSS_HOST_TYPE_CNAME;
  2368. } elseif (OssUtil::isIPFormat($ret_endpoint)) {
  2369. $this->hostType = self::OSS_HOST_TYPE_IP;
  2370. } else {
  2371. $this->hostType = self::OSS_HOST_TYPE_NORMAL;
  2372. }
  2373. return $ret_endpoint;
  2374. }
  2375. /**
  2376. * 用来检查sdk所以来的扩展是否打开
  2377. *
  2378. * @throws OssException
  2379. */
  2380. public static function checkEnv()
  2381. {
  2382. if (function_exists('get_loaded_extensions')) {
  2383. //检测curl扩展
  2384. $enabled_extension = array("curl");
  2385. $extensions = get_loaded_extensions();
  2386. if ($extensions) {
  2387. foreach ($enabled_extension as $item) {
  2388. if (!in_array($item, $extensions)) {
  2389. throw new OssException("Extension {" . $item . "} is not installed or not enabled, please check your php env.");
  2390. }
  2391. }
  2392. } else {
  2393. throw new OssException("function get_loaded_extensions not found.");
  2394. }
  2395. } else {
  2396. throw new OssException('Function get_loaded_extensions has been disabled, please check php config.');
  2397. }
  2398. }
  2399. /**
  2400. //* 设置http库的请求超时时间,单位秒
  2401. *
  2402. * @param int $timeout
  2403. */
  2404. public function setTimeout($timeout)
  2405. {
  2406. $this->timeout = $timeout;
  2407. }
  2408. /**
  2409. * 设置http库的连接超时时间,单位秒
  2410. *
  2411. * @param int $connectTimeout
  2412. */
  2413. public function setConnectTimeout($connectTimeout)
  2414. {
  2415. $this->connectTimeout = $connectTimeout;
  2416. }
  2417. // 生命周期相关常量
  2418. const OSS_LIFECYCLE_EXPIRATION = "Expiration";
  2419. const OSS_LIFECYCLE_TIMING_DAYS = "Days";
  2420. const OSS_LIFECYCLE_TIMING_DATE = "Date";
  2421. //OSS 内部常量
  2422. const OSS_BUCKET = 'bucket';
  2423. const OSS_OBJECT = 'object';
  2424. const OSS_HEADERS = OssUtil::OSS_HEADERS;
  2425. const OSS_METHOD = 'method';
  2426. const OSS_QUERY = 'query';
  2427. const OSS_BASENAME = 'basename';
  2428. const OSS_MAX_KEYS = 'max-keys';
  2429. const OSS_UPLOAD_ID = 'uploadId';
  2430. const OSS_PART_NUM = 'partNumber';
  2431. const OSS_COMP = 'comp';
  2432. const OSS_LIVE_CHANNEL_STATUS = 'status';
  2433. const OSS_LIVE_CHANNEL_START_TIME = 'startTime';
  2434. const OSS_LIVE_CHANNEL_END_TIME = 'endTime';
  2435. const OSS_POSITION = 'position';
  2436. const OSS_MAX_KEYS_VALUE = 100;
  2437. const OSS_MAX_OBJECT_GROUP_VALUE = OssUtil::OSS_MAX_OBJECT_GROUP_VALUE;
  2438. const OSS_MAX_PART_SIZE = OssUtil::OSS_MAX_PART_SIZE;
  2439. const OSS_MID_PART_SIZE = OssUtil::OSS_MID_PART_SIZE;
  2440. const OSS_MIN_PART_SIZE = OssUtil::OSS_MIN_PART_SIZE;
  2441. const OSS_FILE_SLICE_SIZE = 8192;
  2442. const OSS_PREFIX = 'prefix';
  2443. const OSS_DELIMITER = 'delimiter';
  2444. const OSS_MARKER = 'marker';
  2445. const OSS_ACCEPT_ENCODING = 'Accept-Encoding';
  2446. const OSS_CONTENT_MD5 = 'Content-Md5';
  2447. const OSS_SELF_CONTENT_MD5 = 'x-oss-meta-md5';
  2448. const OSS_CONTENT_TYPE = 'Content-Type';
  2449. const OSS_CONTENT_LENGTH = 'Content-Length';
  2450. const OSS_IF_MODIFIED_SINCE = 'If-Modified-Since';
  2451. const OSS_IF_UNMODIFIED_SINCE = 'If-Unmodified-Since';
  2452. const OSS_IF_MATCH = 'If-Match';
  2453. const OSS_IF_NONE_MATCH = 'If-None-Match';
  2454. const OSS_CACHE_CONTROL = 'Cache-Control';
  2455. const OSS_EXPIRES = 'Expires';
  2456. const OSS_PREAUTH = 'preauth';
  2457. const OSS_CONTENT_COING = 'Content-Coding';
  2458. const OSS_CONTENT_DISPOSTION = 'Content-Disposition';
  2459. const OSS_RANGE = 'range';
  2460. const OSS_ETAG = 'etag';
  2461. const OSS_LAST_MODIFIED = 'lastmodified';
  2462. const OS_CONTENT_RANGE = 'Content-Range';
  2463. const OSS_CONTENT = OssUtil::OSS_CONTENT;
  2464. const OSS_BODY = 'body';
  2465. const OSS_LENGTH = OssUtil::OSS_LENGTH;
  2466. const OSS_HOST = 'Host';
  2467. const OSS_DATE = 'Date';
  2468. const OSS_AUTHORIZATION = 'Authorization';
  2469. const OSS_FILE_DOWNLOAD = 'fileDownload';
  2470. const OSS_FILE_UPLOAD = 'fileUpload';
  2471. const OSS_PART_SIZE = 'partSize';
  2472. const OSS_SEEK_TO = 'seekTo';
  2473. const OSS_SIZE = 'size';
  2474. const OSS_QUERY_STRING = 'query_string';
  2475. const OSS_SUB_RESOURCE = 'sub_resource';
  2476. const OSS_DEFAULT_PREFIX = 'x-oss-';
  2477. const OSS_CHECK_MD5 = 'checkmd5';
  2478. const DEFAULT_CONTENT_TYPE = 'application/octet-stream';
  2479. const OSS_SYMLINK_TARGET = 'x-oss-symlink-target';
  2480. const OSS_SYMLINK = 'symlink';
  2481. const OSS_HTTP_CODE = 'http_code';
  2482. const OSS_REQUEST_ID = 'x-oss-request-id';
  2483. const OSS_INFO = 'info';
  2484. const OSS_STORAGE = 'storage';
  2485. const OSS_RESTORE = 'restore';
  2486. const OSS_STORAGE_STANDARD = 'Standard';
  2487. const OSS_STORAGE_IA = 'IA';
  2488. const OSS_STORAGE_ARCHIVE = 'Archive';
  2489. //私有URL变量
  2490. const OSS_URL_ACCESS_KEY_ID = 'OSSAccessKeyId';
  2491. const OSS_URL_EXPIRES = 'Expires';
  2492. const OSS_URL_SIGNATURE = 'Signature';
  2493. //HTTP方法
  2494. const OSS_HTTP_GET = 'GET';
  2495. const OSS_HTTP_PUT = 'PUT';
  2496. const OSS_HTTP_HEAD = 'HEAD';
  2497. const OSS_HTTP_POST = 'POST';
  2498. const OSS_HTTP_DELETE = 'DELETE';
  2499. const OSS_HTTP_OPTIONS = 'OPTIONS';
  2500. //其他常量
  2501. const OSS_ACL = 'x-oss-acl';
  2502. const OSS_OBJECT_ACL = 'x-oss-object-acl';
  2503. const OSS_OBJECT_GROUP = 'x-oss-file-group';
  2504. const OSS_MULTI_PART = 'uploads';
  2505. const OSS_MULTI_DELETE = 'delete';
  2506. const OSS_OBJECT_COPY_SOURCE = 'x-oss-copy-source';
  2507. const OSS_OBJECT_COPY_SOURCE_RANGE = "x-oss-copy-source-range";
  2508. const OSS_PROCESS = "x-oss-process";
  2509. const OSS_CALLBACK = "x-oss-callback";
  2510. const OSS_CALLBACK_VAR = "x-oss-callback-var";
  2511. //支持STS SecurityToken
  2512. const OSS_SECURITY_TOKEN = "x-oss-security-token";
  2513. const OSS_ACL_TYPE_PRIVATE = 'private';
  2514. const OSS_ACL_TYPE_PUBLIC_READ = 'public-read';
  2515. const OSS_ACL_TYPE_PUBLIC_READ_WRITE = 'public-read-write';
  2516. const OSS_ENCODING_TYPE = "encoding-type";
  2517. const OSS_ENCODING_TYPE_URL = "url";
  2518. // 域名类型
  2519. const OSS_HOST_TYPE_NORMAL = "normal";//http://bucket.oss-cn-hangzhou.aliyuncs.com/object
  2520. const OSS_HOST_TYPE_IP = "ip"; //http://1.1.1.1/bucket/object
  2521. const OSS_HOST_TYPE_SPECIAL = 'special'; //http://bucket.guizhou.gov/object
  2522. const OSS_HOST_TYPE_CNAME = "cname"; //http://mydomain.com/object
  2523. //OSS ACL数组
  2524. static $OSS_ACL_TYPES = array(
  2525. self::OSS_ACL_TYPE_PRIVATE,
  2526. self::OSS_ACL_TYPE_PUBLIC_READ,
  2527. self::OSS_ACL_TYPE_PUBLIC_READ_WRITE
  2528. );
  2529. // OssClient版本信息
  2530. const OSS_NAME = "aliyun-sdk-php";
  2531. const OSS_VERSION = "2.3.0";
  2532. const OSS_BUILD = "20180105";
  2533. const OSS_AUTHOR = "";
  2534. const OSS_OPTIONS_ORIGIN = 'Origin';
  2535. const OSS_OPTIONS_REQUEST_METHOD = 'Access-Control-Request-Method';
  2536. const OSS_OPTIONS_REQUEST_HEADERS = 'Access-Control-Request-Headers';
  2537. //是否使用ssl
  2538. private $useSSL = false;
  2539. private $maxRetries = 3;
  2540. private $redirects = 0;
  2541. // 用户提供的域名类型,有四种 OSS_HOST_TYPE_NORMAL, OSS_HOST_TYPE_IP, OSS_HOST_TYPE_SPECIAL, OSS_HOST_TYPE_CNAME
  2542. private $hostType = self::OSS_HOST_TYPE_NORMAL;
  2543. private $requestUrl;
  2544. private $accessKeyId;
  2545. private $accessKeySecret;
  2546. private $hostname;
  2547. private $securityToken;
  2548. private $requestProxy = null;
  2549. private $enableStsInUrl = false;
  2550. private $timeout = 0;
  2551. private $connectTimeout = 0;
  2552. }