Following example demonstrates how to:
- display a private file download prompt to the user (here for a PDF file)
- serve a private image or PDF which will be displayed on a webpage
See https://symfony.com/doc/4.4/components/http_foundation.html#serving-files
Host these files in a directory outside of /public
, so they can be accessed only through the controller and its @Security()
authorization. For example you could create a /private-uploads
directory at the root of your project.
templates/template.html.twig
<a href="{{ path('download_private_pdf', {'name': privatePdfExample.name}) }}">Download</a>
<object data="{{ path('serve_private_pdf', {'name': privatePdfExample.name}) }}" type="application/pdf"></object>
<img src="{{ path('serve_private_image', {'name': privateImageExample.name}) }}">
src/Controller/ServePrivateFileController.php
<?php
namespace App\Controller;
use App\Entity\PrivatePdfExample;
use App\Entity\PrivateImageExample;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\Routing\Annotation\Route;
/**
* Class ServePrivateFileController
* @package App\Controller
*/
class ServePrivateFileController extends DefaultController
{
/**
* Returns a PrivatePdfExample file for download.
*
* @param PrivatePdfExample $privatePdfExample
* @Route("/serve-private-file/pdf/{name}", name="download_private_pdf", methods="GET")
* @Security("is_granted('IS_AUTHENTICATED_REMEMBERED') and user.getId() === privatePdfExample.getUser().getId()")
* @return BinaryFileResponse
*/
public function privatePdfExampleDownload(PrivatePdfExample $privatePdfExample): BinaryFileResponse
{
$name = $privateImageExample->getOriginalName() . '.' . $privateImageExample->getFileExtension();
return $this->fileDownload($privatePdfExample->getPath(), $name);
}
/**
* Returns a PrivatePdfExample file for display.
*
* @param PrivatePdfExample $privatePdfExample
* @Route("/serve-private-file/pdf/{name}", name="serve_private_pdf", methods="GET")
* @Security("is_granted('IS_AUTHENTICATED_REMEMBERED') and user.getId() === privatePdfExample.getUser().getId()")
* @return BinaryFileResponse
*/
public function privatePdfExampleServe(PrivateImageExample $privatePdfExample): BinaryFileResponse
{
return $this->fileServe($privatePdfExample->getPath());
}
/**
* Returns a PrivateImageExample file for display.
*
* @param PrivateImageExample $privateImageExample
* @Route("/serve-private-file/image/{name}", name="serve_private_image", methods="GET")
* @Security("is_granted('IS_AUTHENTICATED_REMEMBERED') and user.getId() === privateImageExample.getUser().getId()")
* @return BinaryFileResponse
*/
public function privateImageExampleServe(PrivateImageExample $privateImageExample): BinaryFileResponse
{
return $this->fileServe($privateImageExample->getPath());
}
/**
* Returns a private file for download.
*
* @param string $path
* @param string $name
* @return BinaryFileResponse
*/
private function fileDownload(string $path, string $name): BinaryFileResponse
{
$absolutePath = $this->getParameter('kernel.root_dir') . '/..' . $path;
$response = new BinaryFileResponse($absolutePath);
$disposition = HeaderUtils::makeDisposition(
HeaderUtils::DISPOSITION_ATTACHMENT,
$name
);
$response->headers->set('Content-Disposition', $disposition);
return $response;
}
/**
* Returns a private file for display.
*
* @param string $path
* @return BinaryFileResponse
*/
private function fileServe(string $path): BinaryFileResponse
{
$absolutePath = $this->getParameter('kernel.root_dir') . '/..' . $path;
return new BinaryFileResponse($absolutePath);
}
}
thank you so much