Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Flysystem Ziparchive Laravel Package

league/flysystem-ziparchive

Flysystem ZipArchive adapter sub-split. Use it to work with ZIP files via Flysystem’s filesystem abstraction. This repo is read-only for packaging; file issues and pull requests on the main Flysystem project: https://github.com/thephpleague/flysystem

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require league/flysystem-ziparchive
    

    Ensure ext-zip is enabled in your php.ini.

  2. Basic Usage

    use League\Flysystem\Filesystem;
    use League\Flysystem\ZipArchive\ZipArchiveAdapter;
    
    $adapter = new ZipArchiveAdapter('/path/to/your/archive.zip');
    $filesystem = new Filesystem($adapter);
    
    // Write a file
    $filesystem->write('file.txt', 'Hello, Zip!');
    
    // Read a file
    echo $filesystem->read('file.txt');
    
  3. First Use Case Dynamically generate a ZIP file on-the-fly for user downloads:

    $zipAdapter = new ZipArchiveAdapter('downloads/archive_' . uniqid() . '.zip');
    $filesystem = new Filesystem($zipAdapter);
    
    // Add files from another filesystem (e.g., local or S3)
    $sourceFilesystem->readStream('document.pdf')
        ->writeTo($filesystem, 'document.pdf');
    
    return response()->streamDownload(
        fn () => $zipAdapter->getZipArchive()->getStream(),
        'archive.zip'
    );
    

Implementation Patterns

Common Workflows

  1. Temporary ZIP Files Use ZipArchiveAdapter for ephemeral ZIP files (e.g., report generation):

    $tempPath = tempnam(sys_get_temp_dir(), 'zip_');
    $adapter = new ZipArchiveAdapter($tempPath, 'w');
    $filesystem = new Filesystem($adapter);
    
    // Add files...
    $filesystem->write('report.csv', $csvData);
    
    // Return file for download
    return response()->download($tempPath);
    
  2. Integration with Other Adapters Chain adapters to read from one storage system and write to ZIP:

    $localAdapter = new LocalAdapter();
    $zipAdapter = new ZipArchiveAdapter('backup.zip');
    $zipFilesystem = new Filesystem($zipAdapter);
    
    // Copy all files from local to ZIP
    foreach ($localFilesystem->listContents('', true) as $file) {
        $localFilesystem->readStream($file->path())
            ->writeTo($zipFilesystem, $file->path());
    }
    
  3. Streaming Large Files Avoid memory issues by streaming files directly into the ZIP:

    $filesystem->writeStream('large_file.iso', fopen('/path/to/large_file.iso', 'r'));
    
  4. Metadata Handling Preserve file metadata (e.g., timestamps) when adding files:

    $filesystem->write('file.txt', 'Content', [
        'visibility' => 'public',
        'timestamp' => time(),
    ]);
    

Laravel-Specific Patterns

  1. Service Provider Binding Bind the adapter to Laravel’s container for reuse:

    public function register()
    {
        $this->app->singleton('zipFilesystem', function ($app) {
            $path = storage_path('app/temp/backup.zip');
            return new Filesystem(new ZipArchiveAdapter($path));
        });
    }
    
  2. Artisan Commands Use ZIP adapters in commands for batch operations:

    public function handle()
    {
        $zipAdapter = new ZipArchiveAdapter('storage/app/backups/backup_' . date('Y-m-d') . '.zip');
        $filesystem = new Filesystem($zipAdapter);
    
        // Add all files from a directory
        $this->addDirectoryToZip($filesystem, 'storage/app/logs');
    
        $this->info('Backup created: ' . $zipAdapter->getPathname());
    }
    
  3. File Uploads Handle user uploads directly into ZIP archives:

    public function store(Request $request)
    {
        $zipAdapter = new ZipArchiveAdapter('storage/app/uploads/archive.zip');
        $filesystem = new Filesystem($zipAdapter);
    
        foreach ($request->file('files') as $file) {
            $filesystem->write(
                $file->hashName(),
                file_get_contents($file->getRealPath())
            );
        }
    
        return back()->with('success', 'Files uploaded to archive!');
    }
    

Gotchas and Tips

Pitfalls

  1. ZipArchive Extension Requirements

    • Ensure ext-zip is installed and enabled. Test with:
      php -m | grep zip
      
    • Fallback: Use league/flysystem-zipstream for PHP < 5.6 or without ext-zip.
  2. File Path Limitations

    • ZipArchive has a 255-character path limit. Use short, consistent paths:
      // Bad: $filesystem->write('very/long/path/file.txt', '...');
      // Good: $filesystem->write('documents/file.txt', '...');
      
  3. Concurrent Access

    • ZIP files are not thread-safe. Avoid concurrent writes to the same file:
      // ❌ Race condition
      $filesystem1->write('file.txt', '...');
      $filesystem2->write('file.txt', '...');
      
      // ✅ Safe
      $filesystem->write('file.txt', '...');
      
  4. Memory Limits

    • Large ZIP files may hit PHP’s memory_limit. Stream files or increase limits:
      ini_set('memory_limit', '512M');
      
  5. Case Sensitivity

    • ZipArchive is case-sensitive on Linux but not on Windows. Normalize paths:
      $normalizedPath = strtolower($path); // For cross-platform compatibility
      

Debugging Tips

  1. Verify ZipArchive Errors Check for silent failures by enabling error reporting:

    $zip = new ZipArchive();
    if ($zip->open('archive.zip', ZipArchive::CREATE) !== true) {
        throw new \RuntimeException('Failed to create ZIP: ' . $zip->getStatusString());
    }
    
  2. Inspect ZIP Contents Use ZipArchive::getFromIndex() to debug missing files:

    $zip = $adapter->getZipArchive();
    for ($i = 0; $i < $zip->numFiles; $i++) {
        echo $zip->getFromIndex($i) . "\n";
    }
    
  3. Handle Corrupted ZIPs Always validate the ZIP before operations:

    if (!$adapter->getZipArchive()->status === ZipArchive::ER_OK) {
        throw new \RuntimeException('Invalid or corrupted ZIP file');
    }
    

Extension Points

  1. Custom ZipArchive Configuration Extend ZipArchiveAdapter for custom behavior:

    class CustomZipAdapter extends ZipArchiveAdapter
    {
        public function __construct(string $path, int $flags = ZipArchive::CREATE)
        {
            parent::__construct($path, $flags | ZipArchive::OVERWRITE);
        }
    }
    
  2. Event Listeners Hook into file operations (e.g., log ZIP modifications):

    $filesystem->addPlugin(new \League\Flysystem\Plugin\EventDispatcherPlugin());
    $dispatcher = $filesystem->getPlugin('eventDispatcher');
    
    $dispatcher->addListener('preWrite', function ($event) {
        Log::debug('Writing to ZIP: ' . $event->file());
    });
    
  3. Fallback Adapters Implement a fallback for unsupported operations:

    class FallbackZipAdapter extends ZipArchiveAdapter
    {
        public function writeStream($path, $resource, array $config = [])
        {
            if (!is_resource($resource)) {
                throw new \InvalidArgumentException('Stream must be a resource');
            }
            return parent::writeStream($path, $resource, $config);
        }
    }
    
  4. Laravel Filesystem Integration Register the adapter as a custom disk in config/filesystems.php:

    'disks' => [
        'zip' => [
            'driver' => 'custom',
            'adapter' => \League\Flysystem\ZipArchive\ZipArchiveAdapter::class,
            'path' => storage_path('app/backups/archive.zip'),
        ],
    ],
    
  5. Performance Optimization

    • Disable compression for large binary files (e.g., videos):
      $adapter = new ZipArchiveAdapter('archive.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);
      $adapter->getZipArchive()->addEmptyDir('videos');
      $adapter->getZipArchive()->addFile('video.mp4', 'videos/video.mp4', ZipArchive::FL_ENC_GUESS, 'video/mp4');
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor