File Downloads¶
Sometimes you want to send files to the browser for download instead of displaying them.
NAF gives you full control to stream files using a custom response.
Downloading a File¶
You can manually create a response that forces a file download:
use function Naf\response;
$filePath = BASE_PATH . '/storage/files/example.pdf';
$fileName = 'example.pdf';
$response = response(file_get_contents($filePath))
->withHeader('Content-Type', 'application/octet-stream')
->withHeader('Content-Disposition', 'attachment; filename="' . $fileName . '"');
return $response;
Content-Typetells the browser this is a generic file download.Content-Disposition: attachmentforces the download dialog.- The file is loaded into the response body.
Example: Download Controller¶
namespace App\Controllers;
use function Naf\{abort, response};
class FileController
{
public function download($filename)
{
$path = BASE_PATH . '/storage/files/' . basename($filename);
if (!is_file($path) || !is_readable($path)) {
abort(404, 'File not found.');
}
return response(file_get_contents($path))
->withHeader('Content-Type', 'application/octet-stream')
->withHeader('Content-Disposition', 'attachment; filename="' . basename($filename) . '"');
}
}
- This example serves flat filenames from an application-owned directory.
basename()strips directory components; it does not check symlinks or authorize access to private files. - Always check if the file actually exists before sending it.
Notes¶
- For large files, you may want to implement streaming to avoid memory issues.
- You can adjust
Content-Typebased on the file type if needed (e.g.,application/pdffor PDFs).
Example for PDF:
return response(file_get_contents($pdfPath))
->withHeader('Content-Type', 'application/pdf')
->withHeader('Content-Disposition', 'attachment; filename="document.pdf"');