Search code examples
symfonyuploadtwigx-sendfile

symfony2 store uploaded file non rootweb


I have problem with uploading files, I'm saving uploaded files in a non public folder (non webroot folder), and then I want to get the webPAth of all uploaded files to use them in a video gallery.

$videos = $repository->getVideosThumbs($this->getUser());

and then in my twig

{% for video in videos %}
         <a href ="{{ path('neoctus_videobundle_default_watchvideo', {'id' : video.id, 'salt' : app.user.salt }) }}" >
            <img id="{{ video.id }}" src="/uploads/images/{{video.imgPath}}" alt="1st image description" height="150" width="150"  />
         </a>
    {% endfor %}

but I can not access the pictures because the folder is not public, I know I have to go through x-sendFile but I do not see how I can send multiple jpeg files in the header and then how recover after the twig.


Solution

  • You could create a controller action to access files that are stored in a non public folder. In that action, you open file and stream in to browser.

    See example at http://php.net/manual/en/function.readfile.php

    You will need to change

    header('Content-Disposition: attachment; filename='.basename($file));
    

    to

    header('Content-Disposition: inline; filename='.basename($file));
    

    UPDATE:

    When you have your controller action that would stream requested file, you can render it in your TWIG by requesting that action with required file identifier:

    <img src="{{ path('route_to_stream_action', {'fileId':'some_id'}) }}">
    

    Browser will treat streamed file the same way as if it was accessed directly, so you can apply any CSS to it.

    UPDATE:

    Sample controller action:

    public function streamFileAction($fileId)
    {
    
        // implement your own logic to retrieve file using $fileId
        $file = $this->getFile($fileId);
    
        $filename = basename($file);
    
        $response = new StreamedResponse();
        $response->setCallback(function () use ($file){
            $handle = fopen($file->getRealPath(), 'rb');
            while (!feof($handle)) {
                $buffer = fread($handle, 1024);
                echo $buffer;
                flush();
            }
            fclose($handle);
        });
        $d = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_INLINE, $filename);
        $response->headers->set('Content-Disposition', $d);
        $response->headers->set('Content-Type', $file->getMimeType());
    
        return $response;
    }