Иногда вам придется отключать рендеринг представления, работающий по умолчанию.
Чтобы это сделать, нужно просто вернуть объект Response
из действия контроллера.
Например, давайте создадим класс DownloadController
и добавим действие "file",
которое позволит пользователям сайта скачивать файлы с вашего вебсайта. Это действие
не нуждается в соответствующем шаблоне представления file.phtml, потому что оно
выбрасывает содержимое файла в стандартный поток вывода PHP.
Добавьте файл DownloadController.php в директорию Controller модуля Application, затем вставьте в файл следующий код:
<?php
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
/**
* Это класс контроллера для управления загрузками файлов.
*/
class DownloadController extends AbstractActionController
{
/**
* Это действие 'file', которое вызывается,
* когда пользователь хочет скачать данный файл.
*/
public function fileAction()
{
// Получить имя файла из GET-переменной
$fileName = $this->params()->fromQuery('name', '');
// Меры предосторожности, чтобы защитить имя файла
$fileName = str_replace("/", "", $fileName); // Убрать слеши
$fileName = str_replace("\\", "", $fileName); // Убрать обратные слеши
// Попытка открыть файл
$path = './data/download/' . $fileName;
if (!is_readable($path)) {
// Поставить код состояния 404 Not Found
$this->getResponse()->setStatusCode(404);
return;
}
// Получить размер файла в байтах
$fileSize = filesize($path);
// HTTP-заголовки
$response = $this->getResponse();
$headers = $response->getHeaders();
$headers->addHeaderLine(
"Content-type: application/octet-stream");
$headers->addHeaderLine(
"Content-Disposition: attachment; filename=\"" .
$fileName . "\"");
$headers->addHeaderLine("Content-length: $fileSize");
$headers->addHeaderLine("Cache-control: private");
// Содержимое файла
$fileContent = file_get_contents($path);
if($fileContent!=false) {
$response->setContent($fileContent);
} else {
// Устанавливаем код состояния 500 Server Error
$this->getResponse()->setStatusCode(500);
return;
}
// Возвращаем Response, чтобы избежать рендеринга шаблона представления
return $this->getResponse();
}
}
Метод действия берет имя параметра из запроса URL (строка 19),
убирает слеши из имени файла (строки 22-23), добавляет HTTP-заголовки
объекту Response
(строки 39-45) и содержимое файла (строки 48-55). Наконец,
он возвращает объект Response
, чтобы отключить рендеринг представления.
Зарегистрируйте класс DownloadController
, добавив следующую строку в
ваш файл module.config.php:
<?php
return [
// ...
'controllers' => [
'factories' => [
// ...
Controller\DownloadController::class => InvokableFactory::class
],
],
// ...
];
Вам также понадобится добавить маршрут к вашему файлу module.config.php.
Измените ключ routes
файла конфигурации следующим образом:
<?php
return [
// ...
'router' => [
'routes' => [
// Add this route for the DownloadController
'download' => [
'type' => Segment::class,
'options' => [
'route' => '/download[/:action]',
'defaults' => [
'controller' => Controller\DownloadController::class,
'action' => 'index',
],
],
],
],
],
// ...
];
Чтобы посмотреть, как работает загрузка файлов, создайте директорию APP_DIR/data/download и положите туда текстовый файл с именем sample.txt. Затем откройте ваш браузер, введите адрес "http://localhost/download/file?name=sample.txt" и нажмите Enter. Браузер начнет загрузку файла sample.txt и предложит вам его куда-нибудь сохранить.