简体   繁体   中英

ZIP file won't download and acts weird with php

I'm working on a system in laravel to make a zip full of photos and download it afterwards.

I decided i really don't want to use libraries for this(it is necessary), so I must use plain php. my controller code:

public function downloadPictures()
{
    $pictures = Input::get('photos');
    $file_paths = array();

    foreach ($pictures as $picture_id) {
         $path = $this->photos->getFilepath($picture_id, 'original');
         array_push($file_paths, $path);
    }

    $zip = new ZipArchive;
    $zip->open('slike.zip', ZipArchive::CREATE);

    foreach ($file_paths as $file) {
        $content = file_get_contents($file);
        $zip->addFromString(basename($file), $content);
    }

    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false);
    header('Content-type: application/zip');
    header('Content-Disposition: attachment; filename="'.basename($zip->filename).'"');

    echo var_dump($zip);
    echo basename($zip->filename);

    $zip->close();

    echo var_dump($zip);
    echo basename($zip->filename);
}

Now with the first part of the code i can say with 100% confidence that i get the right picture paths(that is above the //if (file_exists($file_paths ... ) comment, and i made sure by printing them out and using file_exists )

But then things start getting wonky.

Firstly: when i open the zip the numFiles i tested says there are allready 4 files in it, i have no idea why.

Secondly: when i print the response from this controller function in js frontend(using echo in controller var_dump($zip) ) i get the zip file properties.. name+ numFile+4 (+4 for some reason), but when i $zip->close() i can't access the properites echoed zip properties are empty.

Third: the redirect headers, which i used in both ways: before i closed the $zip and after(currently they are before the closing) are not doing anything.. they should produce a donwload form in a browser, are they not?

If somebody could help me i would be so greatful. I need to do this due sunday and i have been fiddling around this for about 8hrs now.(this is my first time doing this). I have done quite a lot of googling and it works for others. I am on ununtu on nginx, php v5.6 and i installed the php zip extension and i am testing it localy on ubuntu mozilla browser.

UPDATE: It doesn't work in chrome either, so it's not firefoxes problem.

Try this:

public function downloadPictures()
{
    $pictures = Input::get('photos');
    $file_paths = array();

    foreach ($pictures as $picture_id) {
        $path = $this->photos->getFilepath($picture_id, 'original');
        array_push($file_paths, $path);
    }

    $zip = new ZipArchive;
    $zipname = 'silke.zip';
    $zip->open($zipname, ZipArchive::CREATE);

    foreach ($file_paths as $file) {
        $content = file_get_contents($file);
        $zip->addFromString(basename($file), $content);
    }

    header("HTTP/1.1 200 OK");
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false);
    header('Content-type: application/zip');
    header('Content-Disposition: attachment; filename="'.$zipname.'"');
    header('Content-Length: ' . filesize($zipname));

    $zip->close();
    readfile($zipname);
}

Most important is the Content-Length and the readfile line.

Don't echo anything else, it will corrupt the download.

Update: A more selfcontained test:

$testData = array(
    'test1.txt' => 'Test1',
    'test2.txt' => 'Test2',
    'test3.txt' => 'Test3',
    'test4.txt' => 'Test4',
);

$zip = new ZipArchive;
$zipname = 'slike.zip';
$zip->open($zipname, ZipArchive::CREATE);

foreach ($testData as $filename => $content) {
    $zip->addFromString($filename, $content);
}

header("HTTP/1.1 200 OK");
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header('Content-Type: application/force-download');
header('Content-Disposition: attachment; filename="'.$zipname.'"');
header('Content-Length: ' . filesize($zipname));

$zip->close();
readfile($zipname);

Also this has header('Content-Type: application/force-download');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM