Symfony2 создать и скачать ZIP-файл

13

У меня есть одно приложение, которое загружает некоторые файлы, а затем я могу сжимать как zip файл и загружать.

Действие экспорта:

public function exportAction() {
        $files = array();
        $em = $this->getDoctrine()->getManager();
        $doc = $em->getRepository('AdminDocumentBundle:Document')->findAll();
        foreach ($_POST as $p) {
            foreach ($doc as $d) {
                if ($d->getId() == $p) {
                    array_push($files, "../web/".$d->getWebPath());
                }
            }
        }
        $zip = new \ZipArchive();
        $zipName = 'Documents-'.time().".zip";
        $zip->open($zipName,  \ZipArchive::CREATE);
        foreach ($files as $f) {
            $zip->addFromString(basename($f),  file_get_contents($f)); 
        }

        $response = new Response();
    $response->setContent(readfile("../web/".$zipName));
    $response->headers->set('Content-Type', 'application/zip');
    $response->header('Content-disposition: attachment; filename=../web/"'.$zipName.'"');
    $response->header('Content-Length: ' . filesize("../web/" . $zipName));
    $response->readfile("../web/" . $zipName);
    return $response;
    }

все в порядке до заголовка строки. и каждый раз, когда я собираюсь сюда, я получил ошибку: "Warning: readfile (../web/Documents-1385648213.zip): не удалось открыть поток: нет такого файла или каталога"

Что не так?

и почему, когда я загружаю файлы, у этих файлов есть права root, и то же самое происходит с создаваемым zip файлом.

Теги:
zip

6 ответов

8
Лучший ответ

решена:

$zip->close();
header('Content-Type', 'application/zip');
header('Content-disposition: attachment; filename="' . $zipName . '"');
header('Content-Length: ' . filesize($zipName));
readfile($zipName);

очевидно закрытие файла важно;)

  • 0
    Контроллер должен вернуть ответ. Последняя строка должна return new Response(readfile($zipName));
  • 0
    readfile () не возвращает строку, которую можно вставить в ответ. Вы должны использовать потоковый ответ для этого или использовать file_get_contents
15

Пример SYMFONY 3:

public function zipDownloadAllDocumentAction($documents)
{
    $files = array();
    $em = $this->getDoctrine()->getManager();

    foreach ($documents as $d) {
        array_push($files, "../web/" . $d->getWebPath());
    }

    $zip = new \ZipArchive();
    $zipName = 'Documents_' . time() . ".zip";
    $zip->open($zipName,  \ZipArchive::CREATE);
    foreach ($files as $f) {
        $zip->addFromString(basename($f),  file_get_contents($f));
    }
    $zip->close();

    $response = new Response(file_get_contents($zipName));
    $response->headers->set('Content-Type', 'application/zip');
    $response->headers->set('Content-Disposition', 'attachment;filename="' . $zipName . '"');
    $response->headers->set('Content-length', filesize($zipName));

    return $response;
}
  • 1
    Ты гений !!! Спасибо!
2

Поздно, но, возможно, это будет полезно для кого-то еще.

http://symfony.com/doc/2.3/components/http_foundation/introduction.html#serving-files

  • 0
    Пожалуйста, избегайте только ссылок.
0

Начиная с Symfony 3. 2+ может использовать помощник по файлам для загрузки файла в браузере:

public function someAction()
{
    // create zip file
    $zip = ...;

    $this->file($zip);    
}
0

Чтобы завершить ответ Винсента, просто добавьте это право перед возвратом ответа:

...
$response->headers->set('Content-length', filesize($zipName));

unlink($zipName);

return $response;
0

Я думаю, что лучше использовать

$zipFilesIds = $request->request->get('zipFiles')
foreach($zipFilesIds as $zipFilesId){
  //your vérification here 
}

с переменной post вашего идентификатора zip = 'zipFiles'. Лучше всего извлекать все переменные $_POST.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню