0

我正在使用 laravel 中的一个系统来制作一个充满照片的 zip,然后再下载它。

我决定我真的不想为此使用库(这是必要的),所以我必须使用纯 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 属性为空。

第三:重定向标头,我以两种方式使用:在我关闭 $zip 之前和之后(目前它们在关闭之前)没有做任何事情..它们应该在浏览器中生成一个下载表单,不是吗?

如果有人可以帮助我,我会非常感激。我需要在星期天做这个,我现在已经摆弄了大约 8 个小时。(这是我第一次这样做)。我已经做了很多谷歌搜索,它适用于其他人。我在 nginx,php v5.6 上使用 ununtu,我安装了 php zip 扩展,我正在 ubuntu mozilla 浏览器上对其进行本地测试。

更新:它在 chrome 中也不起作用,所以它不是 Firefox 的问题。

4

1 回答 1

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-Lengthreadfile线。

不要回显其他任何内容,它会破坏下载。

更新:一个更独立的测试:

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

于 2016-08-12T12:15:25.860 回答