Skip to content

Commit

Permalink
Expose gzipped file contents (#4)
Browse files Browse the repository at this point in the history
* Fetch stream from S3 and local inputs

* Expose compressed contents as string instead of resource stream

Co-authored-by: Fayez Naccache <[email protected]>
  • Loading branch information
GromNaN and Fayez Naccache authored Sep 5, 2022
1 parent 9bc5605 commit af1398d
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 12 deletions.
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
},
"require": {
"php": ">=7.4",
"ext-zlib": "*",
"async-aws/s3": "^1.5",
"psr/log": "^1.1|^2.0|^3.0"
},
"require-dev": {
"ext-zip": "*",
"symfony/phpunit-bridge": "^5.4|^6.0"
}
}
11 changes: 10 additions & 1 deletion src/Archive.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
<?php


namespace GromNaN\S3Zip;

use GromNaN\S3Zip\Input\InputInterface;

class Archive
{
private InputInterface $input;

/** @var array<int, File> */
private array $filesByIndex;

/** @var array<string, File> */
private array $filesByName;

public function __construct(InputInterface $input)
Expand Down Expand Up @@ -76,11 +79,17 @@ private function initCentralDirectory()
}
}

/**
* @return string[]
*/
public function getFileNames(): array
{
return array_keys($this->filesByName);
}

/**
* @return array<int, File>
*/
public function getFiles(): array
{
return $this->filesByIndex;
Expand Down
18 changes: 16 additions & 2 deletions src/File.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?php


namespace GromNaN\S3Zip;

use GromNaN\S3Zip\Input\InputInterface;
Expand All @@ -14,6 +13,9 @@ class File
private int $length;
private array $options;

/**
* @internal
*/
public function __construct(InputInterface $input, array $options)
{
$this->input = $input;
Expand All @@ -33,14 +35,26 @@ public function getIndex(): int
return $this->options['index'];
}

/**
* Reads and extract file contents
*/
public function getContents($length = 0): string
{
return gzinflate($this->fetch(), $length);
}

/**
* Reads compressed file contents.
* Binary result can be sent as gzipped HTTP response.
*/
public function fetch(): string
{
$chunk = $this->input->fetch($this->offset, $this->length, 'reading file '.$this->name);

$headerSize = 30
+unpack('v', $chunk, 26)[1]
+unpack('v', $chunk, 28)[1];

return gzinflate(substr($chunk, $headerSize), $length);
return substr($chunk, $headerSize);
}
}
1 change: 0 additions & 1 deletion src/Input/HttpInput.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?php


namespace GromNaN\S3Zip\Input;

use AsyncAws\S3\S3Client;
Expand Down
1 change: 0 additions & 1 deletion src/Input/InputInterface.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?php


namespace GromNaN\S3Zip\Input;

interface InputInterface
Expand Down
9 changes: 6 additions & 3 deletions src/Input/LocalInput.php
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
<?php


namespace GromNaN\S3Zip\Input;

class LocalInput implements InputInterface
{
private string $filename;

/**
* @var resource
*/
private $handle;

public function __construct(string $filename)
{
$this->filename = $filename;
$handle = fopen($filename, 'r');
if (false === $filename) {
$handle = fopen($filename, 'rb');
if (false === $handle) {
throw new \RuntimeException('File not found: '.$filename);
}
$this->handle = $handle;
Expand Down
1 change: 0 additions & 1 deletion src/Input/S3Input.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?php


namespace GromNaN\S3Zip\Input;

use AsyncAws\S3\S3Client;
Expand Down
5 changes: 4 additions & 1 deletion tests/Integration/ArchiveTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?php


namespace GromNaN\S3Zip\Tests\Integration;

use GromNaN\S3Zip\Archive;
Expand Down Expand Up @@ -34,6 +33,10 @@ public function testArchive()

$this->assertInstanceOf(File::class, $files[0]);
$this->assertSame($files[5], $archive->getFile($files[5]->getName()));

$contents = $files[3]->getContents();
$compressedContents = $files[3]->fetch();
$this->assertSame($contents, gzinflate($compressedContents));
}

/**
Expand Down
1 change: 0 additions & 1 deletion tests/Integration/LocalArchiveTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?php


namespace GromNaN\S3Zip\Tests\Integration;

use GromNaN\S3Zip\Input\InputInterface;
Expand Down
1 change: 0 additions & 1 deletion tests/Integration/S3ArchiveTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?php


namespace GromNaN\S3Zip\Tests\Integration;

use AsyncAws\S3\S3Client;
Expand Down

0 comments on commit af1398d

Please sign in to comment.