PageRenderTime 36ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 1ms

/vendor/aws/aws-sdk-php/src/Aws/S3/S3Client.php

https://github.com/lslucas/105fm
PHP | 658 lines | 328 code | 54 blank | 276 comment | 23 complexity | d8459f15036b9938759ae448d76d3c0c MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License").
  6. * You may not use this file except in compliance with the License.
  7. * A copy of the License is located at
  8. *
  9. * http://aws.amazon.com/apache2.0
  10. *
  11. * or in the "license" file accompanying this file. This file is distributed
  12. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  13. * express or implied. See the License for the specific language governing
  14. * permissions and limitations under the License.
  15. */
  16. namespace Aws\S3;
  17. use Aws\Common\Client\AbstractClient;
  18. use Aws\Common\Client\ClientBuilder;
  19. use Aws\Common\Client\ExpiredCredentialsChecker;
  20. use Aws\Common\Client\UploadBodyListener;
  21. use Aws\Common\Enum\ClientOptions as Options;
  22. use Aws\Common\Exception\RuntimeException;
  23. use Aws\Common\Exception\InvalidArgumentException;
  24. use Aws\Common\Model\MultipartUpload\AbstractTransfer;
  25. use Aws\S3\Exception\AccessDeniedException;
  26. use Aws\S3\Exception\Parser\S3ExceptionParser;
  27. use Aws\S3\Exception\S3Exception;
  28. use Aws\S3\Model\ClearBucket;
  29. use Aws\S3\Model\MultipartUpload\AbstractTransfer as AbstractMulti;
  30. use Aws\S3\Model\MultipartUpload\UploadBuilder;
  31. use Aws\S3\S3Signature;
  32. use Aws\S3\Sync\DownloadSyncBuilder;
  33. use Aws\S3\Sync\UploadSyncBuilder;
  34. use Guzzle\Common\Collection;
  35. use Guzzle\Http\EntityBody;
  36. use Guzzle\Http\Message\RequestInterface;
  37. use Guzzle\Iterator\FilterIterator;
  38. use Guzzle\Plugin\Backoff\BackoffPlugin;
  39. use Guzzle\Plugin\Backoff\CurlBackoffStrategy;
  40. use Guzzle\Plugin\Backoff\ExponentialBackoffStrategy;
  41. use Guzzle\Plugin\Backoff\HttpBackoffStrategy;
  42. use Guzzle\Plugin\Backoff\TruncatedBackoffStrategy;
  43. use Guzzle\Plugin\Md5\CommandContentMd5Plugin;
  44. use Guzzle\Service\Command\CommandInterface;
  45. use Guzzle\Service\Command\Factory\AliasFactory;
  46. use Guzzle\Service\Command\Factory\CompositeFactory;
  47. use Guzzle\Service\Resource\Model;
  48. use Guzzle\Service\Resource\ResourceIteratorInterface;
  49. /**
  50. * Client to interact with Amazon Simple Storage Service
  51. *
  52. * @method \Aws\S3\S3SignatureInterface getSignature()
  53. * @method Model abortMultipartUpload(array $args = array()) {@command S3 AbortMultipartUpload}
  54. * @method Model completeMultipartUpload(array $args = array()) {@command S3 CompleteMultipartUpload}
  55. * @method Model copyObject(array $args = array()) {@command S3 CopyObject}
  56. * @method Model createBucket(array $args = array()) {@command S3 CreateBucket}
  57. * @method Model createMultipartUpload(array $args = array()) {@command S3 CreateMultipartUpload}
  58. * @method Model deleteBucket(array $args = array()) {@command S3 DeleteBucket}
  59. * @method Model deleteBucketCors(array $args = array()) {@command S3 DeleteBucketCors}
  60. * @method Model deleteBucketLifecycle(array $args = array()) {@command S3 DeleteBucketLifecycle}
  61. * @method Model deleteBucketPolicy(array $args = array()) {@command S3 DeleteBucketPolicy}
  62. * @method Model deleteBucketTagging(array $args = array()) {@command S3 DeleteBucketTagging}
  63. * @method Model deleteBucketWebsite(array $args = array()) {@command S3 DeleteBucketWebsite}
  64. * @method Model deleteObject(array $args = array()) {@command S3 DeleteObject}
  65. * @method Model deleteObjects(array $args = array()) {@command S3 DeleteObjects}
  66. * @method Model getBucketAcl(array $args = array()) {@command S3 GetBucketAcl}
  67. * @method Model getBucketCors(array $args = array()) {@command S3 GetBucketCors}
  68. * @method Model getBucketLifecycle(array $args = array()) {@command S3 GetBucketLifecycle}
  69. * @method Model getBucketLocation(array $args = array()) {@command S3 GetBucketLocation}
  70. * @method Model getBucketLogging(array $args = array()) {@command S3 GetBucketLogging}
  71. * @method Model getBucketNotification(array $args = array()) {@command S3 GetBucketNotification}
  72. * @method Model getBucketPolicy(array $args = array()) {@command S3 GetBucketPolicy}
  73. * @method Model getBucketRequestPayment(array $args = array()) {@command S3 GetBucketRequestPayment}
  74. * @method Model getBucketTagging(array $args = array()) {@command S3 GetBucketTagging}
  75. * @method Model getBucketVersioning(array $args = array()) {@command S3 GetBucketVersioning}
  76. * @method Model getBucketWebsite(array $args = array()) {@command S3 GetBucketWebsite}
  77. * @method Model getObject(array $args = array()) {@command S3 GetObject}
  78. * @method Model getObjectAcl(array $args = array()) {@command S3 GetObjectAcl}
  79. * @method Model getObjectTorrent(array $args = array()) {@command S3 GetObjectTorrent}
  80. * @method Model headBucket(array $args = array()) {@command S3 HeadBucket}
  81. * @method Model headObject(array $args = array()) {@command S3 HeadObject}
  82. * @method Model listBuckets(array $args = array()) {@command S3 ListBuckets}
  83. * @method Model listMultipartUploads(array $args = array()) {@command S3 ListMultipartUploads}
  84. * @method Model listObjectVersions(array $args = array()) {@command S3 ListObjectVersions}
  85. * @method Model listObjects(array $args = array()) {@command S3 ListObjects}
  86. * @method Model listParts(array $args = array()) {@command S3 ListParts}
  87. * @method Model putBucketAcl(array $args = array()) {@command S3 PutBucketAcl}
  88. * @method Model putBucketCors(array $args = array()) {@command S3 PutBucketCors}
  89. * @method Model putBucketLifecycle(array $args = array()) {@command S3 PutBucketLifecycle}
  90. * @method Model putBucketLogging(array $args = array()) {@command S3 PutBucketLogging}
  91. * @method Model putBucketNotification(array $args = array()) {@command S3 PutBucketNotification}
  92. * @method Model putBucketPolicy(array $args = array()) {@command S3 PutBucketPolicy}
  93. * @method Model putBucketRequestPayment(array $args = array()) {@command S3 PutBucketRequestPayment}
  94. * @method Model putBucketTagging(array $args = array()) {@command S3 PutBucketTagging}
  95. * @method Model putBucketVersioning(array $args = array()) {@command S3 PutBucketVersioning}
  96. * @method Model putBucketWebsite(array $args = array()) {@command S3 PutBucketWebsite}
  97. * @method Model putObject(array $args = array()) {@command S3 PutObject}
  98. * @method Model putObjectAcl(array $args = array()) {@command S3 PutObjectAcl}
  99. * @method Model restoreObject(array $args = array()) {@command S3 RestoreObject}
  100. * @method Model uploadPart(array $args = array()) {@command S3 UploadPart}
  101. * @method Model uploadPartCopy(array $args = array()) {@command S3 UploadPartCopy}
  102. * @method waitUntilBucketExists(array $input) Wait until a bucket exists. The input array uses the parameters of the HeadBucket operation and waiter specific settings
  103. * @method waitUntilBucketNotExists(array $input) Wait until a bucket does not exist. The input array uses the parameters of the HeadBucket operation and waiter specific settings
  104. * @method waitUntilObjectExists(array $input) Wait until an object exists. The input array uses the parameters of the HeadObject operation and waiter specific settings
  105. * @method ResourceIteratorInterface getListBucketsIterator(array $args = array()) The input array uses the parameters of the ListBuckets operation
  106. * @method ResourceIteratorInterface getListMultipartUploadsIterator(array $args = array()) The input array uses the parameters of the ListMultipartUploads operation
  107. * @method ResourceIteratorInterface getListObjectsIterator(array $args = array()) The input array uses the parameters of the ListObjects operation
  108. * @method ResourceIteratorInterface getListObjectVersionsIterator(array $args = array()) The input array uses the parameters of the ListObjectVersions operation
  109. * @method ResourceIteratorInterface getListPartsIterator(array $args = array()) The input array uses the parameters of the ListParts operation
  110. *
  111. * @link http://docs.aws.amazon.com/aws-sdk-php/guide/latest/service-s3.html User guide
  112. * @link http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.S3.S3Client.html API docs
  113. */
  114. class S3Client extends AbstractClient
  115. {
  116. const LATEST_API_VERSION = '2006-03-01';
  117. /**
  118. * @var array Aliases for S3 operations
  119. */
  120. protected static $commandAliases = array(
  121. // REST API Docs Aliases
  122. 'GetService' => 'ListBuckets',
  123. 'GetBucket' => 'ListObjects',
  124. 'PutBucket' => 'CreateBucket',
  125. // SDK 1.x Aliases
  126. 'GetBucketHeaders' => 'HeadBucket',
  127. 'GetObjectHeaders' => 'HeadObject',
  128. 'SetBucketAcl' => 'PutBucketAcl',
  129. 'CreateObject' => 'PutObject',
  130. 'DeleteObjects' => 'DeleteMultipleObjects',
  131. 'PutObjectCopy' => 'CopyObject',
  132. 'SetObjectAcl' => 'PutObjectAcl',
  133. 'GetLogs' => 'GetBucketLogging',
  134. 'GetVersioningStatus' => 'GetBucketVersioning',
  135. 'SetBucketPolicy' => 'PutBucketPolicy',
  136. 'CreateBucketNotification' => 'PutBucketNotification',
  137. 'GetBucketNotifications' => 'GetBucketNotification',
  138. 'CopyPart' => 'UploadPartCopy',
  139. 'CreateWebsiteConfig' => 'PutBucketWebsite',
  140. 'GetWebsiteConfig' => 'GetBucketWebsite',
  141. 'DeleteWebsiteConfig' => 'DeleteBucketWebsite',
  142. 'CreateObjectExpirationConfig' => 'PutBucketLifecycle',
  143. 'GetObjectExpirationConfig' => 'GetBucketLifecycle',
  144. 'DeleteObjectExpirationConfig' => 'DeleteBucketLifecycle',
  145. );
  146. /**
  147. * @inheritdoc
  148. */
  149. protected $directory = __DIR__;
  150. /**
  151. * Factory method to create a new Amazon S3 client using an array of configuration options.
  152. *
  153. * @param array|Collection $config Client configuration data
  154. *
  155. * @return self
  156. * @see \Aws\Common\Client\DefaultClient for a list of available configuration options
  157. */
  158. public static function factory($config = array())
  159. {
  160. $exceptionParser = new S3ExceptionParser();
  161. // Configure the custom exponential backoff plugin for retrying S3 specific errors
  162. if (!isset($config[Options::BACKOFF])) {
  163. $config[Options::BACKOFF] = new BackoffPlugin(
  164. new TruncatedBackoffStrategy(3,
  165. new HttpBackoffStrategy(null,
  166. new SocketTimeoutChecker(
  167. new CurlBackoffStrategy(null,
  168. new ExpiredCredentialsChecker($exceptionParser,
  169. new ExponentialBackoffStrategy()
  170. )
  171. )
  172. )
  173. )
  174. )
  175. );
  176. }
  177. $client = ClientBuilder::factory(__NAMESPACE__)
  178. ->setConfig($config)
  179. ->setConfigDefaults(array(
  180. Options::SIGNATURE => new S3Signature(),
  181. Options::VERSION => self::LATEST_API_VERSION,
  182. Options::SERVICE_DESCRIPTION => __DIR__ . '/Resources/s3-%s.php'
  183. ))
  184. ->setExceptionParser($exceptionParser)
  185. ->setIteratorsConfig(array(
  186. 'more_key' => 'IsTruncated',
  187. 'operations' => array(
  188. 'ListBuckets',
  189. 'ListMultipartUploads' => array(
  190. 'limit_param' => 'MaxUploads',
  191. 'token_param' => array('KeyMarker', 'UploadIdMarker'),
  192. 'token_key' => array('NextKeyMarker', 'NextUploadIdMarker'),
  193. ),
  194. 'ListObjects' => array(
  195. 'limit_param' => 'MaxKeys',
  196. 'token_param' => 'Marker',
  197. 'token_key' => 'NextMarker',
  198. ),
  199. 'ListObjectVersions' => array(
  200. 'limit_param' => 'MaxKeys',
  201. 'token_param' => array('KeyMarker', 'VersionIdMarker'),
  202. 'token_key' => array('nextKeyMarker', 'nextVersionIdMarker'),
  203. ),
  204. 'ListParts' => array(
  205. 'limit_param' => 'MaxParts',
  206. 'result_key' => 'Parts',
  207. 'token_param' => 'PartNumberMarker',
  208. 'token_key' => 'NextPartNumberMarker',
  209. ),
  210. )
  211. ))
  212. ->build();
  213. // Use virtual hosted buckets when possible
  214. $client->addSubscriber(new BucketStyleListener());
  215. // Ensure that ACP headers are applied when needed
  216. $client->addSubscriber(new AcpListener());
  217. // Validate and add Content-MD5 hashes
  218. $client->addSubscriber(new CommandContentMd5Plugin());
  219. // Allow for specifying bodies with file paths and file handles
  220. $client->addSubscriber(new UploadBodyListener(array('PutObject', 'UploadPart')));
  221. // Add aliases for some S3 operations
  222. $default = CompositeFactory::getDefaultChain($client);
  223. $default->add(
  224. new AliasFactory($client, self::$commandAliases),
  225. 'Guzzle\Service\Command\Factory\ServiceDescriptionFactory'
  226. );
  227. $client->setCommandFactory($default);
  228. return $client;
  229. }
  230. /**
  231. * Determine if a string is a valid name for a DNS compatible Amazon S3
  232. * bucket, meaning the bucket can be used as a subdomain in a URL (e.g.,
  233. * "<bucket>.s3.amazonaws.com").
  234. *
  235. * @param string $bucket The name of the bucket to check.
  236. *
  237. * @return bool TRUE if the bucket name is valid or FALSE if it is invalid.
  238. */
  239. public static function isValidBucketName($bucket)
  240. {
  241. $bucketLen = strlen($bucket);
  242. if ($bucketLen < 3 || $bucketLen > 63 ||
  243. // Cannot start or end with a '.'
  244. $bucket[0] == '.' || $bucket[$bucketLen - 1] == '.' ||
  245. // Cannot look like an IP address
  246. preg_match('/(\d+\.){3}\d+$/', $bucket) ||
  247. // Cannot include special characters, must start and end with lower alnum
  248. !preg_match('/^[a-z0-9][a-z0-9\-\.]*[a-z0-9]?$/', $bucket)
  249. ) {
  250. return false;
  251. }
  252. return true;
  253. }
  254. /**
  255. * Create a pre-signed URL for a request
  256. *
  257. * @param RequestInterface $request Request to generate the URL for. Use the factory methods of the client to
  258. * create this request object
  259. * @param int|string|\DateTime $expires The time at which the URL should expire. This can be a Unix timestamp, a
  260. * PHP DateTime object, or a string that can be evaluated by strtotime
  261. *
  262. * @return string
  263. * @throws InvalidArgumentException if the request is not associated with this client object
  264. */
  265. public function createPresignedUrl(RequestInterface $request, $expires)
  266. {
  267. if ($request->getClient() !== $this) {
  268. throw new InvalidArgumentException('The request object must be associated with the client. Use the '
  269. . '$client->get(), $client->head(), $client->post(), $client->put(), etc. methods when passing in a '
  270. . 'request object');
  271. }
  272. if ($expires instanceof \DateTime) {
  273. $expires = $expires->getTimestamp();
  274. } elseif (!is_numeric($expires)) {
  275. $expires = strtotime($expires);
  276. }
  277. // Operate on a clone of the request, so the original is not altered
  278. $request = clone $request;
  279. // URL encoding already occurs in the URI template expansion. Undo that and encode using the same encoding as
  280. // GET object, PUT object, etc.
  281. $path = $this->encodeKey(rawurldecode($request->getPath()));
  282. $request->setPath($path);
  283. // Make sure to handle temporary credentials
  284. if ($token = $this->credentials->getSecurityToken()) {
  285. $request->setHeader('x-amz-security-token', $token);
  286. $request->getQuery()->set('x-amz-security-token', $token);
  287. }
  288. // Set query params required for pre-signed URLs
  289. $request->getQuery()
  290. ->set('AWSAccessKeyId', $this->credentials->getAccessKeyId())
  291. ->set('Expires', $expires)
  292. ->set('Signature', $this->signature->signString(
  293. $this->signature->createCanonicalizedString($request, $expires),
  294. $this->credentials
  295. ));
  296. return $request->getUrl();
  297. }
  298. /**
  299. * Returns the URL to an object identified by its bucket and key. If an expiration time is provided, the URL will
  300. * be signed and set to expire at the provided time.
  301. *
  302. * @param string $bucket The name of the bucket where the object is located
  303. * @param string $key The key of the object
  304. * @param mixed $expires The time at which the URL should expire
  305. * @param array $args Arguments to the GetObject command. Additionally you can specify a "Scheme" if you would
  306. * like the URL to use a different scheme than what the client is configured to use
  307. *
  308. * @return string The URL to the object
  309. */
  310. public function getObjectUrl($bucket, $key, $expires = null, array $args = array())
  311. {
  312. $command = $this->getCommand('GetObject', $args + array('Bucket' => $bucket, 'Key' => $key));
  313. if ($command->hasKey('Scheme')) {
  314. $scheme = $command['Scheme'];
  315. $request = $command->remove('Scheme')->prepare()->setScheme($scheme)->setPort(null);
  316. } else {
  317. $request = $command->prepare();
  318. }
  319. return $expires ? $this->createPresignedUrl($request, $expires) : $request->getUrl();
  320. }
  321. /**
  322. * Helper used to clear the contents of a bucket. Use the {@see ClearBucket} object directly
  323. * for more advanced options and control.
  324. *
  325. * @param string $bucket Name of the bucket to clear.
  326. *
  327. * @return int Returns the number of deleted keys
  328. */
  329. public function clearBucket($bucket)
  330. {
  331. $clear = new ClearBucket($this, $bucket);
  332. return $clear->clear();
  333. }
  334. /**
  335. * Determines whether or not a bucket exists by name
  336. *
  337. * @param string $bucket The name of the bucket
  338. * @param bool $accept403 Set to true if 403s are acceptable
  339. * @param array $options Additional options to add to the executed command
  340. *
  341. * @return bool
  342. */
  343. public function doesBucketExist($bucket, $accept403 = true, array $options = array())
  344. {
  345. return $this->checkExistenceWithCommand(
  346. $this->getCommand('HeadBucket', array_merge($options, array(
  347. 'Bucket' => $bucket
  348. ))), $accept403
  349. );
  350. }
  351. /**
  352. * Determines whether or not an object exists by name
  353. *
  354. * @param string $bucket The name of the bucket
  355. * @param string $key The key of the object
  356. * @param array $options Additional options to add to the executed command
  357. *
  358. * @return bool
  359. */
  360. public function doesObjectExist($bucket, $key, array $options = array())
  361. {
  362. return $this->checkExistenceWithCommand(
  363. $this->getCommand('HeadObject', array_merge($options, array(
  364. 'Bucket' => $bucket,
  365. 'Key' => $key
  366. )))
  367. );
  368. }
  369. /**
  370. * Determines whether or not a bucket policy exists for a bucket
  371. *
  372. * @param string $bucket The name of the bucket
  373. * @param array $options Additional options to add to the executed command
  374. *
  375. * @return bool
  376. */
  377. public function doesBucketPolicyExist($bucket, array $options = array())
  378. {
  379. return $this->checkExistenceWithCommand(
  380. $this->getCommand('GetBucketPolicy', array_merge($options, array(
  381. 'Bucket' => $bucket
  382. )))
  383. );
  384. }
  385. /**
  386. * Raw URL encode a key and allow for '/' characters
  387. *
  388. * @param string $key Key to encode
  389. *
  390. * @return string Returns the encoded key
  391. */
  392. public static function encodeKey($key)
  393. {
  394. return str_replace('%2F', '/', rawurlencode($key));
  395. }
  396. /**
  397. * Explode a prefixed key into an array of values
  398. *
  399. * @param string $key Key to explode
  400. *
  401. * @return array Returns the exploded
  402. */
  403. public static function explodeKey($key)
  404. {
  405. // Remove a leading slash if one is found
  406. return explode('/', $key && $key[0] == '/' ? substr($key, 1) : $key);
  407. }
  408. /**
  409. * Register the Amazon S3 stream wrapper and associates it with this client object
  410. *
  411. * @return self
  412. */
  413. public function registerStreamWrapper()
  414. {
  415. StreamWrapper::register($this);
  416. return $this;
  417. }
  418. /**
  419. * Upload a file, stream, or string to a bucket. If the upload size exceeds the specified threshold, the upload
  420. * will be performed using parallel multipart uploads.
  421. *
  422. * @param string $bucket Bucket to upload the object
  423. * @param string $key Key of the object
  424. * @param mixed $body Object data to upload. Can be a Guzzle\Http\EntityBodyInterface, stream resource, or
  425. * string of data to upload.
  426. * @param string $acl ACL to apply to the object
  427. * @param array $options Custom options used when executing commands:
  428. * - params: Custom parameters to use with the upload. The parameters must map to a PutObject
  429. * or InitiateMultipartUpload operation parameters.
  430. * - min_part_size: Minimum size to allow for each uploaded part when performing a multipart upload.
  431. * - concurrency: Maximum number of concurrent multipart uploads.
  432. * - before_upload: Callback to invoke before each multipart upload. The callback will receive a
  433. * Guzzle\Common\Event object with context.
  434. *
  435. * @see Aws\S3\Model\MultipartUpload\UploadBuilder for more options and customization
  436. * @return \Guzzle\Service\Resource\Model Returns the modeled result of the performed operation
  437. */
  438. public function upload($bucket, $key, $body, $acl = 'private', array $options = array())
  439. {
  440. $body = EntityBody::factory($body);
  441. $options = Collection::fromConfig(array_change_key_case($options), array(
  442. 'min_part_size' => AbstractMulti::MIN_PART_SIZE,
  443. 'params' => array(),
  444. 'concurrency' => $body->getWrapper() == 'plainfile' ? 3 : 1
  445. ));
  446. if ($body->getSize() < $options['min_part_size']) {
  447. // Perform a simple PutObject operation
  448. return $this->putObject(array(
  449. 'Bucket' => $bucket,
  450. 'Key' => $key,
  451. 'Body' => $body,
  452. 'ACL' => $acl
  453. ) + $options['params']);
  454. }
  455. // Perform a multipart upload if the file is large enough
  456. $transfer = UploadBuilder::newInstance()
  457. ->setBucket($bucket)
  458. ->setKey($key)
  459. ->setMinPartSize($options['min_part_size'])
  460. ->setConcurrency($options['concurrency'])
  461. ->setClient($this)
  462. ->setSource($body)
  463. ->setTransferOptions($options->toArray())
  464. ->addOptions($options['params'])
  465. ->setOption('ACL', $acl)
  466. ->build()
  467. ->upload();
  468. if ($options['before_upload']) {
  469. $transfer->getEventDispatcher()->addListener(
  470. AbstractTransfer::BEFORE_PART_UPLOAD,
  471. $options['before_upload']
  472. );
  473. }
  474. return $transfer;
  475. }
  476. /**
  477. * Recursively uploads all files in a given directory to a given bucket.
  478. *
  479. * @param string $directory Full path to a directory to upload
  480. * @param string $bucket Name of the bucket
  481. * @param string $keyPrefix Virtual directory key prefix to add to each upload
  482. * @param array $options Associative array of upload options
  483. * - params: Array of parameters to use with each PutObject operation performed during the transfer
  484. * - base_dir: Base directory to remove from each object key
  485. * - force: Set to true to upload every file, even if the file is already in Amazon S3 and has not changed
  486. * - concurrency: Maximum number of parallel uploads (defaults to 10)
  487. * - debug: Set to true or an fopen resource to enable debug mode to print information about each upload
  488. * - multipart_upload_size: When the size of a file exceeds this value, the file will be uploaded using a
  489. * multipart upload.
  490. *
  491. * @see Aws\S3\S3Sync\S3Sync for more options and customization
  492. */
  493. public function uploadDirectory($directory, $bucket, $keyPrefix = null, array $options = array())
  494. {
  495. $options = Collection::fromConfig($options, array('base_dir' => $directory));
  496. $builder = $options['builder'] ?: UploadSyncBuilder::getInstance();
  497. $builder->uploadFromDirectory($directory)
  498. ->setClient($this)
  499. ->setBucket($bucket)
  500. ->setKeyPrefix($keyPrefix)
  501. ->setConcurrency($options['concurrency'] ?: 5)
  502. ->setBaseDir($options['base_dir'])
  503. ->force($options['force'])
  504. ->setOperationParams($options['params'] ?: array())
  505. ->enableDebugOutput($options['debug']);
  506. if ($options->hasKey('multipart_upload_size')) {
  507. $builder->setMultipartUploadSize($options['multipart_upload_size']);
  508. }
  509. $builder->build()->transfer();
  510. }
  511. /**
  512. * Downloads a bucket to the local filesystem
  513. *
  514. * @param string $directory Directory to download to
  515. * @param string $bucket Bucket to download from
  516. * @param string $keyPrefix Only download objects that use this key prefix
  517. * @param array $options Associative array of download options
  518. * - params: Array of parameters to use with each GetObject operation performed during the transfer
  519. * - base_dir: Base directory to remove from each object key when storing in the local filesystem
  520. * - force: Set to true to download every file, even if the file is already on the local filesystem and has not
  521. * changed
  522. * - concurrency: Maximum number of parallel downloads (defaults to 10)
  523. * - debug: Set to true or a fopen resource to enable debug mode to print information about each download
  524. * - allow_resumable: Set to true to allow previously interrupted downloads to be resumed using a Range GET
  525. */
  526. public function downloadBucket($directory, $bucket, $keyPrefix = '', array $options = array())
  527. {
  528. $options = new Collection($options);
  529. $builder = $options['builder'] ?: DownloadSyncBuilder::getInstance();
  530. $builder->setDirectory($directory)
  531. ->setClient($this)
  532. ->setBucket($bucket)
  533. ->setKeyPrefix($keyPrefix)
  534. ->setConcurrency($options['concurrency'] ?: 10)
  535. ->setBaseDir($options['base_dir'])
  536. ->force($options['force'])
  537. ->setOperationParams($options['params'] ?: array())
  538. ->enableDebugOutput($options['debug']);
  539. if ($options['allow_resumable']) {
  540. $builder->allowResumableDownloads();
  541. }
  542. $builder->build()->transfer();
  543. }
  544. /**
  545. * Deletes objects from Amazon S3 that match the result of a ListObjects operation. For example, this allows you
  546. * to do things like delete all objects that match a specific key prefix.
  547. *
  548. * @param string $bucket Bucket that contains the object keys
  549. * @param string $prefix Optionally delete only objects under this key prefix
  550. * @param string $regex Delete only objects that match this regex
  551. * @param array $options Options used when deleting the object:
  552. * - before_delete: Callback to invoke before each delete. The callback will receive a
  553. * Guzzle\Common\Event object with context.
  554. *
  555. * @see Aws\S3\S3Client::listObjects
  556. * @see Aws\S3\Model\ClearBucket For more options or customization
  557. * @return int Returns the number of deleted keys
  558. * @throws RuntimeException if no prefix and no regex is given
  559. */
  560. public function deleteMatchingObjects($bucket, $prefix = '', $regex = '', array $options = array())
  561. {
  562. if (!$prefix && !$regex) {
  563. throw new RuntimeException('A prefix or regex is required, or use S3Client::clearBucket().');
  564. }
  565. $clear = new ClearBucket($this, $bucket);
  566. $iterator = $this->getIterator('ListObjects', array('Bucket' => $bucket, 'Prefix' => $prefix));
  567. if ($regex) {
  568. $iterator = new FilterIterator($iterator, function ($current) use ($regex) {
  569. return preg_match($regex, $current['Key']);
  570. });
  571. }
  572. $clear->setIterator($iterator);
  573. if (isset($options['before_delete'])) {
  574. $clear->getEventDispatcher()->addListener(ClearBucket::BEFORE_CLEAR, $options['before_delete']);
  575. }
  576. return $clear->clear();
  577. }
  578. /**
  579. * Determines whether or not a resource exists using a command
  580. *
  581. * @param CommandInterface $command Command used to poll for the resource
  582. * @param bool $accept403 Set to true if 403s are acceptable
  583. *
  584. * @return bool
  585. * @throws S3Exception|\Exception if there is an unhandled exception
  586. */
  587. protected function checkExistenceWithCommand(CommandInterface $command, $accept403 = false)
  588. {
  589. try {
  590. $command->execute();
  591. $exists = true;
  592. } catch (AccessDeniedException $e) {
  593. $exists = (bool) $accept403;
  594. } catch (S3Exception $e) {
  595. $exists = false;
  596. if ($e->getResponse()->getStatusCode() >= 500) {
  597. // @codeCoverageIgnoreStart
  598. throw $e;
  599. // @codeCoverageIgnoreEnd
  600. }
  601. }
  602. return $exists;
  603. }
  604. }