123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- <?php
- namespace Aws\S3;
- use Aws\Api\Parser\PayloadParserTrait;
- use Aws\CommandInterface;
- use Aws\Exception\AwsException;
- use Aws\HandlerList;
- use Aws\ResultInterface;
- use Aws\S3\Exception\PermanentRedirectException;
- use Aws\S3\Exception\S3Exception;
- use GuzzleHttp\Promise\PromiseInterface;
- use GuzzleHttp\Promise\RejectedPromise;
- use Psr\Http\Message\ResponseInterface;
- /**
- * A trait providing S3-specific functionality. This is meant to be used in
- * classes implementing \Aws\S3\S3ClientInterface
- */
- trait S3ClientTrait
- {
- use PayloadParserTrait;
- /**
- * @see S3ClientInterface::upload()
- */
- public function upload(
- $bucket,
- $key,
- $body,
- $acl = 'private',
- array $options = []
- ) {
- return $this
- ->uploadAsync($bucket, $key, $body, $acl, $options)
- ->wait();
- }
- /**
- * @see S3ClientInterface::uploadAsync()
- */
- public function uploadAsync(
- $bucket,
- $key,
- $body,
- $acl = 'private',
- array $options = []
- ) {
- return (new ObjectUploader($this, $bucket, $key, $body, $acl, $options))
- ->promise();
- }
- /**
- * @see S3ClientInterface::copy()
- */
- public function copy(
- $fromB,
- $fromK,
- $destB,
- $destK,
- $acl = 'private',
- array $opts = []
- ) {
- return $this->copyAsync($fromB, $fromK, $destB, $destK, $acl, $opts)
- ->wait();
- }
- /**
- * @see S3ClientInterface::copyAsync()
- */
- public function copyAsync(
- $fromB,
- $fromK,
- $destB,
- $destK,
- $acl = 'private',
- array $opts = []
- ) {
- $source = [
- 'Bucket' => $fromB,
- 'Key' => $fromK,
- ];
- if (isset($opts['version_id'])) {
- $source['VersionId'] = $opts['version_id'];
- }
- $destination = [
- 'Bucket' => $destB,
- 'Key' => $destK
- ];
- return (new ObjectCopier($this, $source, $destination, $acl, $opts))
- ->promise();
- }
- /**
- * @see S3ClientInterface::registerStreamWrapper()
- */
- public function registerStreamWrapper()
- {
- StreamWrapper::register($this);
- }
- /**
- * @see S3ClientInterface::registerStreamWrapperV2()
- */
- public function registerStreamWrapperV2()
- {
- StreamWrapper::register(
- $this,
- 's3',
- null,
- true
- );
- }
- /**
- * @see S3ClientInterface::deleteMatchingObjects()
- */
- public function deleteMatchingObjects(
- $bucket,
- $prefix = '',
- $regex = '',
- array $options = []
- ) {
- $this->deleteMatchingObjectsAsync($bucket, $prefix, $regex, $options)
- ->wait();
- }
- /**
- * @see S3ClientInterface::deleteMatchingObjectsAsync()
- */
- public function deleteMatchingObjectsAsync(
- $bucket,
- $prefix = '',
- $regex = '',
- array $options = []
- ) {
- if (!$prefix && !$regex) {
- return new RejectedPromise(
- new \RuntimeException('A prefix or regex is required.')
- );
- }
- $params = ['Bucket' => $bucket, 'Prefix' => $prefix];
- $iter = $this->getIterator('ListObjects', $params);
- if ($regex) {
- $iter = \Aws\filter($iter, function ($c) use ($regex) {
- return preg_match($regex, $c['Key']);
- });
- }
- return BatchDelete::fromIterator($this, $bucket, $iter, $options)
- ->promise();
- }
- /**
- * @see S3ClientInterface::uploadDirectory()
- */
- public function uploadDirectory(
- $directory,
- $bucket,
- $keyPrefix = null,
- array $options = []
- ) {
- $this->uploadDirectoryAsync($directory, $bucket, $keyPrefix, $options)
- ->wait();
- }
- /**
- * @see S3ClientInterface::uploadDirectoryAsync()
- */
- public function uploadDirectoryAsync(
- $directory,
- $bucket,
- $keyPrefix = null,
- array $options = []
- ) {
- $d = "s3://$bucket" . ($keyPrefix ? '/' . ltrim($keyPrefix, '/') : '');
- return (new Transfer($this, $directory, $d, $options))->promise();
- }
- /**
- * @see S3ClientInterface::downloadBucket()
- */
- public function downloadBucket(
- $directory,
- $bucket,
- $keyPrefix = '',
- array $options = []
- ) {
- $this->downloadBucketAsync($directory, $bucket, $keyPrefix, $options)
- ->wait();
- }
- /**
- * @see S3ClientInterface::downloadBucketAsync()
- */
- public function downloadBucketAsync(
- $directory,
- $bucket,
- $keyPrefix = '',
- array $options = []
- ) {
- $s = "s3://$bucket" . ($keyPrefix ? '/' . ltrim($keyPrefix, '/') : '');
- return (new Transfer($this, $s, $directory, $options))->promise();
- }
- /**
- * @see S3ClientInterface::determineBucketRegion()
- */
- public function determineBucketRegion($bucketName)
- {
- return $this->determineBucketRegionAsync($bucketName)->wait();
- }
- /**
- * @see S3ClientInterface::determineBucketRegionAsync()
- *
- * @param string $bucketName
- *
- * @return PromiseInterface
- */
- public function determineBucketRegionAsync($bucketName)
- {
- $command = $this->getCommand('HeadBucket', ['Bucket' => $bucketName]);
- $handlerList = clone $this->getHandlerList();
- $handlerList->remove('s3.permanent_redirect');
- $handlerList->remove('signer');
- $handler = $handlerList->resolve();
- return $handler($command)
- ->then(static function (ResultInterface $result) {
- return $result['@metadata']['headers']['x-amz-bucket-region'];
- }, function (AwsException $e) {
- $response = $e->getResponse();
- if ($response === null) {
- throw $e;
- }
- if ($e->getAwsErrorCode() === 'AuthorizationHeaderMalformed') {
- $region = $this->determineBucketRegionFromExceptionBody(
- $response
- );
- if (!empty($region)) {
- return $region;
- }
- throw $e;
- }
- return $response->getHeaderLine('x-amz-bucket-region');
- });
- }
- private function determineBucketRegionFromExceptionBody(ResponseInterface $response)
- {
- try {
- $element = $this->parseXml($response->getBody(), $response);
- if (!empty($element->Region)) {
- return (string)$element->Region;
- }
- } catch (\Exception $e) {
- // Fallthrough on exceptions from parsing
- }
- return false;
- }
- /**
- * @see S3ClientInterface::doesBucketExist()
- */
- public function doesBucketExist($bucket)
- {
- return $this->checkExistenceWithCommand(
- $this->getCommand('HeadBucket', ['Bucket' => $bucket])
- );
- }
- /**
- * @see S3ClientInterface::doesBucketExistV2()
- */
- public function doesBucketExistV2($bucket, $accept403 = false)
- {
- $command = $this->getCommand('HeadBucket', ['Bucket' => $bucket]);
- try {
- $this->execute($command);
- return true;
- } catch (S3Exception $e) {
- if (
- ($accept403 && $e->getStatusCode() === 403)
- || $e instanceof PermanentRedirectException
- ) {
- return true;
- }
- if ($e->getStatusCode() === 404) {
- return false;
- }
- throw $e;
- }
- }
- /**
- * @see S3ClientInterface::doesObjectExist()
- */
- public function doesObjectExist($bucket, $key, array $options = [])
- {
- return $this->checkExistenceWithCommand(
- $this->getCommand('HeadObject', [
- 'Bucket' => $bucket,
- 'Key' => $key
- ] + $options)
- );
- }
- /**
- * @see S3ClientInterface::doesObjectExistV2()
- */
- public function doesObjectExistV2(
- $bucket,
- $key,
- $includeDeleteMarkers = false,
- array $options = []
- ){
- $command = $this->getCommand('HeadObject', [
- 'Bucket' => $bucket,
- 'Key' => $key
- ] + $options
- );
- try {
- $this->execute($command);
- return true;
- } catch (S3Exception $e) {
- if ($includeDeleteMarkers
- && $this->useDeleteMarkers($e)
- ) {
- return true;
- }
- if ($e->getStatusCode() === 404) {
- return false;
- }
- throw $e;
- }
- }
- private function useDeleteMarkers($exception)
- {
- $response = $exception->getResponse();
- return !empty($response)
- && $response->getHeader('x-amz-delete-marker');
- }
- /**
- * Determines whether or not a resource exists using a command
- *
- * @param CommandInterface $command Command used to poll for the resource
- *
- * @return bool
- * @throws S3Exception|\Exception if there is an unhandled exception
- */
- private function checkExistenceWithCommand(CommandInterface $command)
- {
- try {
- $this->execute($command);
- return true;
- } catch (S3Exception $e) {
- if ($e->getAwsErrorCode() == 'AccessDenied') {
- return true;
- }
- if ($e->getStatusCode() >= 500) {
- throw $e;
- }
- return false;
- }
- }
- /**
- * @see S3ClientInterface::execute()
- */
- abstract public function execute(CommandInterface $command);
- /**
- * @see S3ClientInterface::getCommand()
- */
- abstract public function getCommand($name, array $args = []);
- /**
- * @see S3ClientInterface::getHandlerList()
- *
- * @return HandlerList
- */
- abstract public function getHandlerList();
- /**
- * @see S3ClientInterface::getIterator()
- *
- * @return \Iterator
- */
- abstract public function getIterator($name, array $args = []);
- }
|