Jason Swett
Jason Swett

Reputation: 45094

Serve a download of an uploaded file in Symfony2

My Symfony2 app allows users to upload files. I'd like to users to also be able to download their files.

If I were doing straight PHP, I'd just output the appropriate headers, then output the contents of the file. How would I do this within a Symfony2 controller?

(If you use a hard-coded filename in your answer, that's good enough for me.)

Upvotes: 8

Views: 7222

Answers (3)

crmpicco
crmpicco

Reputation: 17181

Have a look at the VichUploaderBundle

It will allow you to do this:

/**
 * @param integer $assetId
 *
 * @return Response
 */
public function downloadAssetAction($assetId)
{
    if (!$courseAsset = $this->get('crmpicco.repository.course_asset')->findOneById($assetId)) {
        throw new NotFoundHttpException('Requested asset (' . $assetId . ') does not exist.');
    }

    $downloadHandler = $this->get('vich_uploader.download_handler');

    return $downloadHandler->downloadObject($courseAsset->getFile(), 'assetFile', null, $courseAsset->getName());
}

Upvotes: 0

leek
leek

Reputation: 12121

Any reason why you do not want to bypass Symfony entirely and just serve the file via your HTTP server (Apache, Nginx, etc)?

Just have the uploaded files dropped somewhere in the document root and let your HTTP server do what it does best.

Update: While the Symfony2 code posted by @Jason Swett will work for 99% of cases - I just wanted to make sure to document the alternative(s). Another way of securing downloads would be to use the mod_secdownload module of Lighttpd. This would be the ideal solution for larger files or files that need to be served quickly with little-as-possible memory usage.

Upvotes: 3

Jason Swett
Jason Swett

Reputation: 45094

I ended up doing this:

/** 
 * Serves an uploaded file.
 *
 * @Route("/{id}/file", name="event_file")
 * @Template()
 */
public function fileAction($id)
{   
    $em = $this->getDoctrine()->getEntityManager();

    $entity = $em->getRepository('VNNPressboxBundle:Event')->find($id);

    if (!$entity) {
        throw $this->createNotFoundException('Unable to find Event entity.');
    }   

    $headers = array(
        'Content-Type' => $entity->getDocument()->getMimeType(),
        'Content-Disposition' => 'attachment; filename="'.$entity->getDocument()->getName().'"'
    );  

    $filename = $entity->getDocument()->getUploadRootDir().'/'.$entity->getDocument()->getName();

    return new Response(file_get_contents($filename), 200, $headers);
}   

Upvotes: 15

Related Questions