From 4465296d2e06a0e8808d51f8200268e8e83adf2d Mon Sep 17 00:00:00 2001 From: Jon Skarpeteig Date: Sun, 12 Apr 2015 15:07:52 +0200 Subject: [PATCH] Added stream feature to AwsS3 adapter. This remove issues with out of memory on large files, and optimize delivery path to client. --- src/Gaufrette/Adapter/AwsS3.php | 15 +++++ src/Gaufrette/Stream/Http.php | 107 ++++++++++++++++++++++++++++++++ src/Gaufrette/Stream/Local.php | 6 +- 3 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 src/Gaufrette/Stream/Http.php diff --git a/src/Gaufrette/Adapter/AwsS3.php b/src/Gaufrette/Adapter/AwsS3.php index 5605de7f4..96bd9fe01 100644 --- a/src/Gaufrette/Adapter/AwsS3.php +++ b/src/Gaufrette/Adapter/AwsS3.php @@ -4,6 +4,7 @@ use Gaufrette\Adapter; use Aws\S3\S3Client; +use Gaufrette\Stream\Http; /** * Amazon S3 adapter using the AWS SDK for PHP v2.x @@ -221,6 +222,20 @@ public function isDirectory($key) return count($result['Contents']) > 0; } + /** + * {@inheritDoc} + */ + public function createStream($key) { + $context = stream_context_create(array( + 's3' => array( + 'seekable' => true + ) + )); + + $this->service->registerStreamWrapper(); + return new Http("s3://$this->bucket/$key", $context); + } + /** * Ensures the specified bucket exists. If the bucket does not exists * and the create option is set to true, it will try to create the diff --git a/src/Gaufrette/Stream/Http.php b/src/Gaufrette/Stream/Http.php new file mode 100644 index 000000000..b743f3f49 --- /dev/null +++ b/src/Gaufrette/Stream/Http.php @@ -0,0 +1,107 @@ + + */ +class Http extends Local implements Stream +{ + + protected $context; + + /** + * Constructor + * + * @param string $path + */ + public function __construct($path, $context = null) + { + $this->context = ($context === null) ? stream_context_create() : $context; + $this->path = $path; + } + + /** + * {@inheritDoc} + */ + public function open(StreamMode $mode) + { + if ($mode->allowsRead() && $mode->allowsWrite()) { + throw new \RuntimeException(sprintf('File "%s" cannot be opened with read and write mode simultaneously', $this->path)); + } + + try { + $fileHandle = @fopen($this->path, $mode->getMode(), false, $this->context); + } catch (\Exception $e) { + $fileHandle = false; + } + + if (false === $fileHandle) { + throw new \RuntimeException(sprintf('File "%s" cannot be opened', $this->path)); + } + + $this->mode = $mode; + $this->fileHandle = $fileHandle; + + return true; + } + + /** + * {@inheritDoc} + */ + public function stat() + { + if ($this->fileHandle) { + + /** + * 0 dev device number + * 1 ino inode number * + * 2 mode inode protection mode + * 3 nlink number of links + * 4 uid userid of owner * + * 5 gid groupid of owner * + * 6 rdev device type, if inode device + * 7 size size in bytes + * 8 atime time of last access (Unix timestamp) + * 9 mtime time of last modification (Unix timestamp) + * 10 ctime time of last inode change (Unix timestamp) + * 11 blksize blocksize of filesystem IO ** + * 12 blocks number of 512-byte blocks allocated ** + * On Windows this will always be 0. + * * Only valid on systems supporting the st_blksize type - other systems (e.g. Windows) return -1. + */ + + /** + * Directories must be a mode like 040777 (octal), and files a mode like 0100666. + * + * If you wish the file to be executable, use 7s instead of 6s. The last 3 digits + * are exactly the same thing as what you pass to chmod. 040000 defines a directory, + * and 0100000 defines a file. + */ + + return array( + 'dev' => 0, + 'ino' => 0, + 'mode' => 0100666, + 'nlink' => 0, + 'uid' => 0, + 'gid' => 0, + 'rdev ' => 0, + 'size' => filesize($this->path), + 'atime' => 0, + 'mtime' => filemtime($this->path), + 'ctime' => 0, + 'blksize' => - 1, + 'blocks' => - 1 + ); + } + + return false; + } +} diff --git a/src/Gaufrette/Stream/Local.php b/src/Gaufrette/Stream/Local.php index 6ed17833b..cfee4ea61 100644 --- a/src/Gaufrette/Stream/Local.php +++ b/src/Gaufrette/Stream/Local.php @@ -12,9 +12,9 @@ */ class Local implements Stream { - private $path; - private $mode; - private $fileHandle; + protected $path; + protected $mode; + protected $fileHandle; /** * Constructor