thephpleague / flysystem

Abstraction for local and remote filesystems
https://flysystem.thephpleague.com
MIT License
13.36k stars 827 forks source link

Error while creating ZIP file with Flysystem and ZipAdapter! #1009

Closed Rikijs closed 5 years ago

Rikijs commented 5 years ago

Question

Q A
Symfony 4.2.3
PHP 7.2.14
OneUpFlysystemBundle 3.0.3

I am having hard time creating ZIP file using Flysystem and ZipAdapter while also using mount manager.

At the moment i am stuck! I am getting an error: "Could not open zip archive at:zip:\\test123\my_zip_test.zip, error: 5"

It probably is not related to access rights as all files are located in public folder and ZIP file also is supposed to be created in the same public folder.

my code

<?php

namespace App\Controller;

use App\UltraHelpers\UltraAccess;
use App\UltraHelpers\UltraWhereabouts;
use League\Flysystem\Adapter\Local;
use League\Flysystem\Filesystem;
use League\Flysystem\MountManager;
use League\Flysystem\ZipArchive\ZipArchiveAdapter;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;

class ZipController extends BaseController
{
    /**
     * @Route("/zip", name="zip")
     */
    public function createZipArchive(Request $request, SessionInterface $session, MountManager $mountManager, ContainerInterface $container)
    {

        $kernel_project_dir = $container->getParameter('kernel.project_dir');
        $adapter_public = new Local($kernel_project_dir .'/public/uploads/');
        $adapter_zip = new ZipArchiveAdapter($kernel_project_dir .'/public/uploads/');

        $filesystem_public = new Filesystem($adapter_public);
        $filesystem_zip = new Filesystem($adapter_zip);

        $mountManager->mountFilesystem('public', $filesystem_public);
        $mountManager->mountFilesystem('zip', $filesystem_zip);

        $public_path = 'public://test123/';
        $public_zip = 'zip://test123/my_zip_test.zip';

        $adapter_zip->openArchive($public_zip);

        // get all files in directory
        $files_2_zip = $mountManager->listContents($public_path, false);

        // itereate trough all files in directory
        foreach ($files_2_zip as $object)
        {
            $mountManager->copy($object['path'], $public_zip);
        }

        $adapter_zip->getArchive()->close();

        return $this->render('default/create_zip_archive.html.twig', []);
    }
}

I created a question on StackOverflow with detailed information about this issue. https://stackoverflow.com/questions/54931915/error-while-creating-zip-file-in-symfony4-with-flysystem-and-zipadapter

Thank you for ideas and suggestions! Help would be greatly appreciated.

frankdejonge commented 5 years ago

Have you checked the file permissions of the directory you want to write it to?

Rikijs commented 5 years ago

Hello, @frankdejonge Copying files to public works fine, but ZIP file in the same path is not created. So i conclude that it should not be permissions issue.

Rikijs commented 5 years ago

I just rechecked - i have full access in public and its sub folders.

frankdejonge commented 5 years ago

It seems like you’re trying to re-set the path of the zip, you shouldn’t do that. You should create the zip adapter with the path of the zip, just a file path not a zip:// path.

Rikijs commented 5 years ago

So ZipAdapter is not supposed/made to work with mount manager?

I need to create many ZIPs on demand (with different files inside them). Also ZIPs file name would be different every time. And mount manager could alleviate that task as it works fine for 2 local mount points.

Rikijs commented 5 years ago

I am setting the path to directory and then adding name of the ZIP file to that using mount manager. And it results in an error.

Rikijs commented 5 years ago

Thank you @frankdejonge. I managed to crate ZIP archives, but without mount manager. Yet, the question stands: "Why ZipAdapter is not made to work with mount manager (as it is very useful feature of Flysystem)?"

frankdejonge commented 5 years ago

Ok, I think I see what's going on. You're using the adapter incorrectly. You need to view copy action as a source, destination pair, not a destination directory. It doesn't work like the cp or mv functions in your terminal.

Rikijs commented 5 years ago

Hi @frankdejonge! So how would one make ZIP archive while using MountManager correctly?

frankdejonge commented 5 years ago

It doesn't really make sense to create a zip using mount manager. If you want to have a portable way of creating zips even from remote sources you should use the following setup: A source filesystem from where to read the files from. A destination filesystem where you want to write the eventual ZIP. A zip filesystem to create the zip. You use the zip filesystem to write the files to, this will always be at a local location. After writing all files from the source to the zip you can unset the zip filesystem, this causes the write of the zip file (limitation of PHP's ZipArchive implementation). You can now open a read stream from the zip file location, and use writeStream to write it to the destination filesystem.

This setup will make it agnostic of the source and destination filesystem. The zip will ALWAYS be local, the other filesystems can't make the zips.

Rikijs commented 5 years ago

Thank you @frankdejonge for detailed explanation.

frankdejonge commented 5 years ago

I'll close this issue for now. If you have other questions, lemme know, I'll see what I can do.