Sometimes, you would need to disable the default view rendering.
To do that, just return the Response
object from the the controller's action.
For example, let's create a DownloadController
class, and add the "file" action,
which would allow site users to download files from your website. This
action does not need a corresponding file.phtml view template, because it just dumps file contents
to PHP standard output stream.
Add the DownloadController.php file to Controller directory of Application module, then put the following code into the file:
<?php
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
/**
* This is the controller class for managing file downloads.
*/
class DownloadController extends AbstractActionController
{
/**
* This is the 'file' action that is invoked
* when a user wants to download the given file.
*/
public function fileAction()
{
// Get the file name from GET variable
$fileName = $this->params()->fromQuery('name', '');
// Take some precautions to make file name secure
$fileName = str_replace("/", "", $fileName); // Remove slashes
$fileName = str_replace("\\", "", $fileName); // Remove back-slashes
// Try to open file
$path = './data/download/' . $fileName;
if (!is_readable($path)) {
// Set 404 Not Found status code
$this->getResponse()->setStatusCode(404);
return;
}
// Get file size in bytes
$fileSize = filesize($path);
// Write HTTP headers
$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");
// Write file content
$fileContent = file_get_contents($path);
if($fileContent!=false) {
$response->setContent($fileContent);
} else {
// Set 500 Server Error status code
$this->getResponse()->setStatusCode(500);
return;
}
// Return Response to avoid default view rendering
return $this->getResponse();
}
}
The action method takes the name parameter from URL's query part (line 19),
removes slashes from file name (lines 22-23), adds HTTP headers to Response
object
(lines 39-45) and file contents (lines 48-55). Finally, it returns the Response
object
to disable the default view rendering.
Register the DownloadController
class by adding the following line to
your module.config.php file:
<?php
return [
// ...
'controllers' => [
'factories' => [
// ...
Controller\DownloadController::class => InvokableFactory::class
],
],
// ...
];
You will also need to add a route to your module.config.php (a route tells ZF3 to what URL to map the
controller action). Modify the routes
key of the config file as follows:
<?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',
],
],
],
],
],
// ...
];
To see how the file download works, create APP_DIR/data/download directory and put some text file named sample.txt in it. Then open your web browser and type the URL "http://localhost/download/file?name=sample.txt" in your browser's navigation bar and press the Enter key. The browser will download the sample.txt file and offer you to save it to some location.