Serving files for download with Symfony3 and Flysystem
<h2>Introduction</h2>

<p>I am using:</p>

<ul>
<li>Windows 10 Pro</li>
<li>XAMPP with PHP v7.0.9</li>
<li>Symfony v3.1.6</li>
<li>Doctrine v2.5.4</li>
<li>StofDoctrineExtensionsBundle <a href="https://github.com/stof/StofDoctrineExtensionsBundle" rel="nofollow noreferrer">[1]</a> in order to
manage Tree structure.</li>
<li>OneupUploaderBundle <a href="https://github.com/1up-lab/OneupUploaderBundle" rel="nofollow noreferrer">[2]</a> in order to Upload files</li>
<li>OneupFlysystemBundle <a href="https://github.com/1up-lab/OneupFlysystemBundle" rel="nofollow noreferrer">[3]</a> for filesystem abstraction</li>
</ul>

<h2>Setting up</h2>

<p>I did setup the tree structure (that represents directories and files) and file upload with <code>OneupUploaderBundle</code> and <code>Flysystem</code> endpoint.</p>

<p>File upload is organized to upload to folder named <code>data</code> that exists in project root folder. Uploading is working fine and even paths with custom sub-directories for different uploads work (for example <code>data/project_001/test1.txt</code> and <code>data/project_002/test2.txt</code>)!</p>

<h2>Problem</h2>

<p>I need to serve files that users had uploaded earlier.</p>

<p>At the moment</p>

<ul>
<li><p>I am getting error (with controller ending 1)</p>

<pre><code>The file "Project_9999/2_Divi/bbb.pdf" does not exist
500 Internal Server Error - FileNotFoundException
</code></pre></li>
<li><p>and error (with controller ending 2)</p>

<pre><code>Catchable Fatal Error: Object of class League\Flysystem\File could not be converted to string
500 Internal Server Error - ContextErrorException
</code></pre></li>
</ul>

<p>Note that <code>$exists</code> return <code>true</code> - so file is definitely there!</p>

<h2>Code</h2>

<p>relevant part of config.yml</p>

<pre><code>oneup_uploader:
    mappings:
        gallery:
            storage:
                type: flysystem
                filesystem: oneup_flysystem.gallery_filesystem

            frontend: blueimp
            enable_progress: true
            namer: app.upload_unique_namer

            allowed_mimetypes: [ image/png, image/jpg, image/jpeg, image/gif ]
            max_size: 10485760s

oneup_flysystem:
    adapters:
        my_adapter:
            local:
                directory: "%kernel.root_dir%/../data"

    filesystems:
        gallery:
            adapter: my_adapter
</code></pre>

<p>Controller action</p>

<pre><code>&lt;?php

public function projectDownloadFileAction($file_id, Request $request)
{
    $em = $this-&gt;getDoctrine()-&gt;getManager();
    $repo = $em-&gt;getRepository('AppBundle:FileTree');
    $ultra = $this-&gt;get('app.ultra_helpers');

    $selected_file = $repo-&gt;getFileTreeNodeByIdArray($file_id);
    $item_name = $selected_file[0]['item_name'];
    $item_extension = $selected_file[0]['item_extension'];

    $activeProject = $this-&gt;get('session')-&gt;get('active_project');
    $activeProjectSelectedNodePath = $this-&gt;get('session')-&gt;get('active_project_selected_node_path');
    $item_file_name = $item_name .'.'. $item_extension;
    $complete_file_path = $activeProject['secret_path'] . $activeProjectSelectedNodePath .'/'. $item_file_name;
    dump($complete_file_path);

    ENDING -1-
    ENDING -2-
}
</code></pre>

<p>Ending 1</p>

<pre><code>    $downloadable_file = new \SplFileInfo($complete_file_path);
    dump($downloadable_file);
    $response = new BinaryFileResponse($downloadable_file);

    // Set headers
    $response-&gt;headers-&gt;set('Cache-Control', 'private');
    $response-&gt;headers-&gt;set('Content-Type', mime_content_type($downloadable_file));
    $response-&gt;headers-&gt;set('Content-Disposition', $response-&gt;headers-&gt;makeDisposition(
        ResponseHeaderBag::DISPOSITION_ATTACHMENT,
        $downloadable_file-&gt;getFilename()
    ));

    return $response;
</code></pre>

<p>Ending 2</p>

<pre><code>    $filesystem = $this-&gt;get('oneup_flysystem.gallery_filesystem');
    $exists = $filesystem-&gt;has($complete_file_path);
    if (!$exists)
    {
        throw $this-&gt;createNotFoundException();
    }
    dump($exists);

    $downloadable_file = $filesystem-&gt;get($complete_file_path);
    dump($downloadable_file);

    $response = new BinaryFileResponse($complete_file_path);
    $response-&gt;trustXSendfileTypeHeader();
    $response-&gt;setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT);

    return $response;
</code></pre>

<h2>Update 1</h2>

<p>I tried to supply absolute path to the <code>Ending 1</code> variable `$complete_file_path, but got only errors. For example:</p>

<ul>
<li><p><code>File not found at path: C:\DEV\tree_and_upload\data\Project_9999\1_Viens\test1.txt
500 Internal Server Error - FileNotFoundException</code></p></li>
<li><p><code>File not found at path: C:/DEV/tree_and_upload/data/Project_9999/1_Viens/test1.txt
500 Internal Server Error - FileNotFoundException</code></p></li>
</ul>

<p>But it did not make any diference - I got access error. Perhaps Symfony is actively restricting access to <code>data</code> folder in the root of the project...</p>

<h2>Question</h2>

<p>How do one would serve files from <code>data</code> folder that is situated in project root folder and using <code>Flysystem</code> filesystem abstraction layer with <code>Local</code> adapter?</p>

<h2>Conclusion</h2>

<p>What am I missing?</p>

<p>Please advise.</p>

<p>Thank you for your time and knowledge.</p>