diff --git a/src/Seeker/S3ObjectSeeker.php b/src/Seeker/S3ObjectSeeker.php new file mode 100644 index 0000000..f6f44f2 --- /dev/null +++ b/src/Seeker/S3ObjectSeeker.php @@ -0,0 +1,141 @@ +path = $path; + try { + $this->size = filesize($path); + if ($this->size === FALSE) { + throw new InvalidArgumentException( + "The provided S3 Object could not be opened" + ); + } + } catch (Exception $e) { + throw new InvalidArgumentException( + "The provided S3 Object could not be opened: " . $e->getMessage() + ); + } + } + + /** + * Destructor function to ensure the file descriptor is closed. + */ + public function __destruct() { + if ($this->stream) { + fclose($this->stream); + } + } + + /** + * @inheritDoc + */ + public function retrieveStart(int $length, int $offset = 0): ?string { + // Bail out if the parameters are invalid + if ($length <= 0 || $offset < 0 || ($offset + $length) > $this->size) { + return NULL; + } + + try { + $context = stream_context_create( + [ + 's3' => [ + 'Range' => "bytes=" . $offset . "-" . ($offset + $length - 1), + 'seekable' => FALSE, + ], + ] + ); + + $this->stream = fopen($this->path, "r", FALSE, $context); + $data = ''; + while (!feof( $this->stream)) { + $data .= fread($this->stream, 8192); + } + if (!$data or strlen($data)!= $length) { + return NULL; + } + return $data; + } catch (Exception $e) { + user_error("Caught exception: " . $e->getMessage(), E_USER_WARNING); + return NULL; + } + } + + /** + * @inheritDoc + */ + public function retrieveEnd(int $length, int $offset = 0): ?string { + if ($length <= 0 || ($offset + $length) > $this->size) { + return NULL; + } + // Make sure we can handle both positive and negative expressions of the offset, just in case. + $offset = abs($offset); + + // Make sure we are not trying to seek past the start of the file. + if ($offset > $this->size) { + $offset = $this->size; + } + + try { + $to = ($this->size - $offset - 1); + $from = $to - $length + 1; + $context = stream_context_create( + [ + 's3' => [ + 'Range' => "bytes=" . $from + . "-" . $to, + 'seekable' => FALSE, + ], + ] + ); + $data = ''; + $this->stream = fopen($this->path, "r", FALSE, $context); + while (!feof( $this->stream)) { + $data .= fread($this->stream, 8192); + } + // Be sure to close the stream resource when you're done with it + if (!$data || strlen($data)!= $length) { + return NULL; + } + return $data; + } catch (Exception $e) { + user_error("Caught exception: " . $e->getMessage(), E_USER_WARNING); + return NULL; + } + } +} \ No newline at end of file