2

I'm trying to download a zip from a folder that i have on my app (Laravel 5.8), it's working but they skip all empty folders, and I need them in the zip.

I already tried ZipArchive (php) and chumper/zipper from composer.

Any idea of how can i do this?

This is a Linux Server, running MySQL 5, PHP 7.2 and Apache2.

$files = glob($folder_path);
\Zipper::make($folder_path.'/'.$folder_main_name.'.zip')->add($files)->close();

This lib only accepts glob, but if you have any solution that works, i can easily abandon this.

Matheus Sartori
  • 149
  • 2
  • 10
  • Have you tried to put a dot file (like a ".keep" or whatever) in the empty folders to see what happens ? – Ugo T. Apr 30 '19 at 18:51
  • Have you tried not using a lib and just calling the zip command from Linux? It's way faster and more feature rich than what people are trying to reinvent in various libraries. If you are not building something that should be ported to Windows, than that could solve all your issues. Let me know if you are willing to go down that path. – asiby Apr 30 '19 at 18:52
  • Yeah, i added a file named "Icon_" and works. But i need the folders empty, because it will be upload on another server, and it must be empty. – Matheus Sartori Apr 30 '19 at 18:53
  • @asiby I have not tried that yet. I will do it now. Ty! – Matheus Sartori Apr 30 '19 at 18:53
  • Yep. For many things that the Operating System can do, I would rather let it do it. For instance, finding some files or folders based on complex criteria. I needed to file all the git repos, then I do `exec("find %baseDir -type d -name .git", $output, $returnCode)`. And I use `strtr()` to replace `%baseDir` with the directory I am scanning. For zipping stuff, I would use `tar` and do `exec("tar czf compressed.tar.gz folder-to-compress", $output, $returnCode)` – asiby Apr 30 '19 at 19:10
  • `tar` has a better compressing ratio and often does not need to be installed. You can, if you want, replace the name of the archive and the `folder-to-compress` with a placeholder that you can then replace using `strtr()`. That way, it is parameterized and if you place it in a function, then you can call it with any values. And the tar command will not skip empty folders by default. – asiby Apr 30 '19 at 19:12

2 Answers2

3
// Initialize archive object
$zip = new ZipArchive();
$zip->open($zipFilename, ZipArchive::CREATE | ZipArchive::OVERWRITE);

// Create recursive directory iterator
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($rootPath), RecursiveIteratorIterator::LEAVES_ONLY);

foreach ($files as $name => $file)
{
    // Get real and relative path for current file
    $filePath = $file->getRealPath();
    $relativePath = substr($filePath, strlen($rootPath) + 1);

    if (!$file->isDir())
    {
        // Add current file to archive
        $zip->addFile($filePath, $relativePath);
    }else {
        if($relativePath !== false)
            $zip->addEmptyDir($relativePath);
    }
}

// Zip archive will be created only after closing object
$zip->close();

Hi. I modified the previous answer and now I get the zip file including the empty folders. I hope this helps.

LRHD
  • 46
  • 4
1
// Get real path for our folder
$rootPath = realpath('folder-to-zip');

// Initialize archive object
$zip = new ZipArchive();
$zip->open('file.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);

// Create recursive directory iterator
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($rootPath),
    RecursiveIteratorIterator::LEAVES_ONLY
);

foreach ($files as $name => $file)
{
    // Is this a directory?
    if (!$file->isDir())
    {
        // Get real and relative path for current file
        $filePath = $file->getRealPath();
        $relativePath = substr($filePath, strlen($rootPath) + 1);

        // Add current file to archive
        $zip->addFile($filePath, $relativePath);
    }
    else {
        $end2 = substr($file,-2);
        if ($end2 == "/.") {
           $folder = substr($file, 0, -2);
           $zip->addEmptyDir($folder);
        }
    }
}

// Zip archive will be created only after closing object
$zip->close();

** Try this. Off of the top of my head, not tested. But its the general idea.

R. Smith
  • 551
  • 4
  • 10