gpht/zipper-client

There is no license information available for the latest version (1.3.1) of this package.

Client SDK For creating Zips of S3 files via our Zipper Service

1.3.1 2025-03-06 09:32 UTC

This package is auto-updated.

Last update: 2025-03-06 08:33:36 UTC


README

Coverage Badge

The Zipper SDK enables developers to create ZIP files directly from S3 objects and acts as a client SDK for the Zipper Service. Once a ZIP file is created, a service bus message containing the download link is sent to notify the consuming application.

Installation

To install the Zipper SDK, use Composer:

composer require gpht/zipper-client

Setup

Prerequisite

Note: If you are using Core, the Zipper SDK is pre-installed. In such cases, skip directly to the Usage section.

Dependencies

The Zipper SDK relies on p-service-bus for seamless communication with the Zipper Service. Ensure that this dependency is correctly configured in your project.

Service Bus Messages

  • Outgoing Message:

    • CreateZip: Sent to the Zipper Service, containing the manifest required for ZIP creation.
  • Incoming Message:

    • ZipCreated: Received from the Zipper Service after ZIP creation, containing the download link.

Both messages must be configured in the service bus to enable proper message transmission and handling.

  • Message Handler:
    • OnZipCreated: A handler that processes the ZipCreated message. It should be registered with the service bus.

Service Creation

The Zipper service must be created using a factory method and injected into the service container for dependency management.

Symfony Dependency Injection Example

The following example demonstrates how to configure the Zipper service in a Symfony application:

use GDXbsv\PServiceBus\Bus;
use Gotphoto\Zipper\Handler\OnZipCreated;
use Gotphoto\Zipper\Message\CreateZip;
use Gotphoto\Zipper\Message\ZipCreated;
use Gotphoto\Zipper\Zipper;
use Gotphoto\Zipper\ZipperFactory;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

return static function (ContainerConfigurator $containerConfigurator): void {
    $s = $containerConfigurator->services();

    // Register the ZipperFactory as a service
    $s->set(ZipperFactory::class);

    // Register message classes for service bus communication
    $s->set(CreateZip::class)->autoconfigure();
    $s->set(ZipCreated::class)->autoconfigure();

    // Register the OnZipCreated handler with required dependencies
    $s->set(OnZipCreated::class)
        ->args([
            service(LoggerInterface::class), // Inject Logger for logging events
            service(Bus::class) // Inject the service bus for message handling
        ])
        ->autoconfigure();

    // Register the Zipper service with a factory
    $s->set(Zipper::class)
        ->factory([service(ZipperFactory::class), 'create']) // Factory method to create Zipper
        ->args([
            service(Bus::class) // Inject service bus into the Zipper instance
        ]);
};

Explanation:

  1. ZipperFactory creates instances of the Zipper service.
  2. The service bus (Bus) is injected into both the Zipper and the OnZipCreated handler.
  3. Messages (CreateZip, ZipCreated) are registered and autoconfigured to work seamlessly.

Usage

Storage Configuration

ZIP files are stored in region-specific S3 buckets based on the region specified during setup:

  • EU Region: zipper-eu
  • US Region: zipper-us

The ZIP files are retained for 72 hours before automatic deletion.

Creating a Zipper Instance

Use the ZipperFactory class to create a Zipper instance. Below is an example:

use Gotphoto\Zipper\ZipperFactory;

// Create an instance of Zipper using the factory
$zipper = (new ZipperFactory())->create(
    $serviceBus, // Inject the service bus for communication
    's3+http://AAAABBBB:CCCCDDDD@local-s3/000000000000?region=eu-west-1&bucket=providerdata' // S3 DSN for storage
);

Details:

  • The DSN specifies the target bucket where the ZIP manifest is stored.
  • Ensure the DSN credentials have sufficient write access to the bucket.
  • Alternatively, set the ZIPPER_BUCKET_DSN environment variable for easier configuration.

Setting Metadata (Optional)

Add custom metadata to the ZIP file using the addMetadata method:

$zipper->addMetadata("property", $this->currentUser->labId);

Metadata will be returned in the ZipCreated message for additional processing.

Custom Filename (Optional)

Set a specific filename for the ZIP file:

$zipper->setFilename('my-archive');

If no filename is provided, one will be auto-generated.

Region Selection (Optional)

By default, the region is set to EU if not explicitly specified.

Define the storage region for the ZIP file:

$zipper->setRegion('US'); // Options: 'EU', 'US'

Return Value

When the create() method is called, the $zipper instance will return the UUID of the created ZIP file. This UUID can be used for future reference, such as tracking or retrieving ZIP-related information.

Below are different examples for creating ZIP files:

Example A: Adding a single file to the root of the ZIP file.

$zipper
    ->addFile('path/to/file1.jpg', 'file1.jpg', 'sourceBucket') // Add file to ZIP
    ->addZipCreatedCommand(
        NotifyMeWhenZipCreated::class, // Command triggered upon ZIP creation
        [
            'argument1' => 'value1',
            'argument2' => 'value2',
        ]
    )
    ->create(); // Initiate ZIP creation

Example B: Adding a file inside a folder.

use Gotphoto\Zipper\Folder;

// Create a folder for the ZIP
$folder = new Folder('my_folder');
$folder->addFile('path/to/file1.jpg', 'file1.jpg', 'sourceBucket');

$zipper
    ->addFolder($folder) // Add folder to ZIP
    ->addZipCreatedCommand(
        NotifyMeWhenZipCreated::class,
        [
            'argument1' => 'value1',
            'argument2' => 'value2',
        ]
    )
    ->create();

Example C: Adding multiple files to the root and a folder.

$folder = new Folder('my_folder');
$folder->addFile('path/to/file2.jpg', 'file2.jpg', 'sourceBucket');

$zipper
    ->addFile('path/to/file1.jpg', 'file1.jpg', 'sourceBucket') // Add first file to root
    ->addFolder($folder) // Add folder to ZIP
    ->addZipCreatedCommand(
        NotifyMeWhenZipCreated::class,
        [
            'argument1' => 'value1',
            'argument2' => 'value2',
        ]
    )
    ->create();

Example D: Including metadata and setting a custom filename.

$zipper
    ->addMetadata("property", $this->currentUser->labId) // Add metadata
    ->setFilename('custom-archive') // Set custom filename
    ->addFile('path/to/file1.jpg', 'file1.jpg', 'sourceBucket')
    ->addZipCreatedCommand(
        NotifyMeWhenZipCreated::class,
        [
            'argument1' => 'value1',
            'argument2' => 'value2',
        ]
    )
    ->create();

Example E: Including metadata and setting a custom filename that would be stored in US.

$zipper
    ->addMetadata("property", $this->currentUser->labId) // Add metadata
    ->setFilename('custom-archive') // Set custom filename
    ->setRegion('US') // Set region to US
    ->addFile('path/to/file1.jpg', 'file1.jpg', 'sourceBucket')
    ->addZipCreatedCommand(
        NotifyMeWhenZipCreated::class,
        [
            'argument1' => 'value1',
            'argument2' => 'value2',
        ]
    )
    ->create();

Command Implementation

The NotifyMeWhenZipCreated command must implement the Gotphoto\Zipper\ZipCreatedCommand interface. This interface defines the behavior triggered once a ZIP file is successfully created. For instance, the command can be used to:

  • Send an email notification.
  • Trigger further processing tasks.

Source Bucket Requirements

The Zipper Service must have access to the source bucket containing the files to be zipped. The following buckets have been tested:

  • providerdata
  • img3.fotocdn.de

Future Improvements

  1. Allow configuring DSN buckets using environment variables.
  2. Introduce object representation for files to enhance readability and usability.
  3. Develop a Symfony bundle for easier integration.