Skip to content

Commit

Permalink
support zipping media
Browse files Browse the repository at this point in the history
  • Loading branch information
QuentinGab committed Jan 14, 2024
1 parent c669e92 commit 8d2ee6b
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"require": {
"php": "^8.1",
"illuminate/contracts": "^10.0",
"maennchen/zipstream-php": "^3.1",
"pbmedia/laravel-ffmpeg": "^8.3",
"spatie/image": "^3.0.0",
"spatie/laravel-package-tools": "^1.14.0",
Expand Down
78 changes: 78 additions & 0 deletions src/MediaZipper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace Finller\Media;

use Finller\Media\Models\Media;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Contracts\Support\Responsable;
use Illuminate\Support\Collection;
use Symfony\Component\HttpFoundation\StreamedResponse;
use ZipStream\ZipStream;

class MediaZipper implements Responsable
{
/**
* @param Collection<int, Media> $media
*/
public function __construct(
public Collection $media = new Collection(),
public string $fileName = 'media.zip',
public array $zipStreamOptions = [],
) {
$this->zipStreamOptions['outputName'] = $fileName;
}

public function toFile(Filesystem $storage, string $path, array $options = []): string|false
{
$tempStream = fopen('php://memory', 'w+');

$zipStream = $this->getZipStream([
'outputStream' => $tempStream,
]);

$success = $storage->writeStream($path, $tempStream, $options);

fclose($tempStream);

return $success ? $path : false;
}

public function getZipStream(array $options = [])
{
$zip = new ZipStream(
...$this->zipStreamOptions,
...$options,
);

foreach ($this->media as $item) {
$stream = $item->readStream();

$zip->addFileFromStream(
fileName: $item->file_name,
stream: $stream
);

if (is_resource($stream)) {
fclose($stream);
}
}

$zip->finish();

return $zip;
}

/**
* Create an HTTP response that represents the object.
*
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
public function toResponse($request): StreamedResponse
{
return new StreamedResponse(fn () => $this->getZipStream(), 200, [
'Content-Disposition' => "attachment; filename=\"{$this->fileName}\"",
'Content-Type' => 'application/octet-stream',
]);
}
}
30 changes: 30 additions & 0 deletions tests/Feature/MediaZipperTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

use Finller\Media\Database\Factories\MediaFactory;
use Finller\Media\MediaZipper;
use Finller\Media\Models\Media;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

it('zip media and store it in a file', function () {
$storage = Storage::fake('media');

$media = collect([
MediaFactory::new()->make(),
MediaFactory::new()->make(),
])->each(function (Media $media) {
$media->storeFile(
file: UploadedFile::fake()->image('foo.jpg'),
collection_name: 'avatar',
name: 'avatar',
disk: 'media'
);
});

$zipper = new MediaZipper($media);

$zipper->toFile($storage, $zipper->fileName);

Storage::disk('media')->assertExists($zipper->fileName);

});

0 comments on commit 8d2ee6b

Please sign in to comment.