ZIP-файл не загружается и ведет себя странно с php

Я работаю над системой в Laravel, чтобы сделать полный архив фотографий и загрузить его потом.

Я решил, что я действительно не хочу использовать библиотеки для этого (это необходимо), поэтому я должен использовать обычный php. мой код контроллера:

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);
}

Теперь с первой частью кода я могу сказать со 100% уверенностью, что я получаю правильные пути изображения (то есть выше //if (file_exists($file_paths ... ) комментарий, и я убедился, распечатав их и используя file_exists)

Но потом все становится странным.

Во-первых: когда я открываю zip-файл, то протестированный мной numFiles говорит, что в нем уже 4 файла, я понятия не имею, почему.

Во-вторых: когда я печатаю ответ от этой функции контроллера в интерфейсе js (используя echo в контроллере var_dump($zip)) я получаю свойства файла zip.. name+ numFile+4 (+4 по некоторым причинам), но когда я $zip->close() я не могу получить доступ к свойствам.

В-третьих: заголовки перенаправления, которые я использовал обоими способами: до того, как я закрыл $zip, и после (в настоящее время они находятся перед закрытием) ничего не делают... они должны создать форму в браузере, не так ли?

Если бы кто-то мог мне помочь, я был бы так рад. Мне нужно сделать это в воскресенье, и я возился с этим около 8 часов (это мой первый раз, когда я делаю это). Я довольно много гуглил, и это работает для других. Я использую ununtu на nginx, php v5.6, и я установил расширение php zip, и я тестирую его локально в браузере Ubuntu Mozilla.

ОБНОВЛЕНИЕ: Это не работает в Chrome, так что это не проблема Firefox.

1 ответ

Попробуй это:

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);
}

Наиболее важным является Content-Lengthи readfileлиния.

Не повторяйте ничего другого, это повредит загрузку.

Обновление: более автономный тест:

$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);

Также это имеет header('Content-Type: application/force-download');

Другие вопросы по тегам