Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

eggplantSword's avatar

Create zip with file in Storage public disk

I want to eventually use this code as a Job but for now I'm testing it as a regular function in a controller just to make sure it works. All the files are in the storage/app/public folder this is what I have so far. I'm following a tutorial but it doesn't seem to be the correct code.

public function getZip()
{ 
    $zip = new ZipArchive;
    $fileName = 'ReportesTodos.zip';
    if ($zip->open(public_path($fileName), ZipArchive::CREATE) === TRUE) {
        foreach (Storage::files('public') as $name) {
            $file = Storage::get($name);

            if ($name != 'public/.gitignore') {
                $relativeNameInZipFile = basename($file);
                $zip->addFile($file, $relativeNameInZipFile);
            }
        }
        $zip->close();
    }
    return response()->download(public_path($fileName));
}

When I run this function I get this error

ZipArchive::addFile() expects parameter 1 to be a valid path, string given

I think I'm not getting the files correctly but I'm not sure because if I do a dd($file); it returns the name of the file but I don't think the file itself, I'm not sure what a file is supposed to look like in a dd.

What am I doing wrong?

0 likes
19 replies
eggplantSword's avatar

I changed

$file = Storage::get($name);

to

$file = Storage::url($name);

And that seemed to get the path but now I can't download it I get this error

The file "C:\xampp\htdocs\u\public\ReportesTodos.zip" does not exist

eggplantSword's avatar

I did, and it returns this message

The "public/storage" directory already exists.

haztakki's avatar

If you navigate to the file in Explorer, does it exist and if so where is it located? The path.

Try:

asset('storage/ReportesTodos.zip')
eggplantSword's avatar

I did

return asset('storage/ReportesTodos.zip');

And this is the response

http://dev.u.com/storage/ReportesTodos.zip

But if I look in my project files in PhpStorm it's not there

haztakki's avatar

Does the file physically exist in the public folder? Is it inside storage there also? Did you check it? You can also use storage_path instead of public_path as well.

Delete the storage folder and link it again. Then test it.

eggplantSword's avatar

@haz_ The file is no where to be found not in the public folder, or in the storage folder, it's like the zip file is never actually being created.

haztakki's avatar

Well you don't upload anything? You also try to open a ZIP that doesn't exist? What are you trying to achieve?

eggplantSword's avatar

@haz_ I'm trying to create and download a zip file and has all the files that are already in the storage/app/public folder. After some dds I found out that the line

 $zip->addFile($file, $relativeNameInZipFile);

returns false, so the files aren't getting added to the zip, what could be the issue here?

haztakki's avatar

Ah, just noticed you was trying to create it if it didn't exist. Simplify the problem down. This works:

Route::get('/create-zip', function () {
    $zip = new ZipArchive;

    if (true === ($zip->open('test.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE))) {
        $zip->addFile(public_path('file1.txt'), 'file1.txt');
        $zip->addFile(public_path('file2.txt'), 'file2.txt');
        $zip->addFile(public_path('file3.txt'), 'file3.txt');
        $zip->close();
        echo 'success';
    } else {
        echo 'error';
    }

    return response()->download(public_path('test.zip'), 'test.zip');
});

I have 3 .txt files named file1, file2 and file3 in my public directory. Slowly build upon it. Have it loop through for a directory to add files manually, etc.

All the info needed was provided.

https://www.php.net/manual/en/ziparchive.addfile.php

https://laravel.com/docs/7.x/filesystem#downloading-files

Hope it helps.

eggplantSword's avatar

I still get the same error

The file "C:\xampp\htdocs\u\public\ResportesTodos.zip" does not exist

haztakki's avatar

What did you do? Create three .txt files as named above. Copy the route and hit it in the browser.

/create-zip

Once this is working, then move it to your controller and modify.

eggplantSword's avatar

@haz_ ok that one works as is, but when I move those .txt into the public/storage I get the same error that the file doesn't exist, how do I look in that folder and not just in the public folder?

haztakki's avatar

This:

public_path('storage\file1.txt')

        $zip->addFile(public_path('storage\file1.txt'), 'file1.txt');
        $zip->addFile(public_path('storage\file2.txt'), 'file2.txt');
        $zip->addFile(public_path('storage\file3.txt'), 'file3.txt');

If you use storage_path then it uses the storage folder instead.

https://laravel.com/docs/7.x/helpers#method-storage-path

Make sure the files are located in /storage and that you have linked the storage.

php artisan storage:link

This will make a symbolic link of them in public/storage directory.

eggplantSword's avatar

@haz_ yea that was it, now it downloads, however it download all the files inside a folder called storage in the zip so when you open the zip it's not immediately the files but a folder and the files are in there. Is there a way to fix that?

This code is what I have now

$zip = new ZipArchive;

if (true === ($zip->open('ReportesTodos.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE))) {
    foreach (Storage::allFiles('public') as $name) {
        if ($name !== 'public/.gitignore') {
            $name = str_replace('public/', 'storage\\', $name);
            $zip->addFile(public_path($name), str_replace('public/', '', $name));
        }
    }
    $zip->close();
}

return response()->download(public_path('ReportesTodos.zip'), 'ReportesTodos.zip');
haztakki's avatar

I don't understand what you mean. Can you clarify a bit?

If the files are going to be uploaded, you can also just do:

        $zip->addFile(storage_path('app/public/file1.txt'), 'file1.txt');
        $zip->addFile(storage_path('app/public/file2.txt'), 'file2.txt');
        $zip->addFile(storage_path('app/public/file3.txt'), 'file3.txt');

Are you talking about not having a folder in the ZIP called storage?

eggplantSword's avatar

@haz_ the zip downloads fine, when I open it I see a folder called storage and inside that folder there are all the correct files, I wanted to know if there is a way to have the files be inside the zip without thestorage folder.

The reason I change the name is because it has that public/ at the beginning before the actual filename that was causing the problem and I replace it with the correct prefix storage\.

haztakki's avatar
haztakki
Best Answer
Level 51

You can use basename to achieve this.

    $zip = new ZipArchive;

    if (true === ($zip->open('ReportesTodos.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE))) {
        foreach (Storage::allFiles('public') as $file) {
            $name = basename($file);
            if ($name !== '.gitignore') {
                $zip->addFile(public_path('storage\' . $name), $name);
            }
        }
        $zip->close();
    }

    return response()->download(public_path('ReportesTodos.zip'), 'ReportesTodos.zip');

Hope it helps.

1 like

Please or to participate in this conversation.