This method allows you to secure your data delivery behind some type of authentication without having any additional overhead usually associated with loading up media being delivered by php. This method uses apache directly to deliver the file requested after a user has been authenticated. You can use Symfony’s build in authentication or any method you choose I do not specify anyone in particular in this post.

X-Sendfile
mod_xsendfile is a really useful Apache2 module that processes X-SENDFILE headers registered by the original output handler. If the module encouners the X-SENDFILE header it will discard all output and send the file specified directly by the header instead, using Apache internals – including all optimizations like caching-headers and sendfile.

Setting up X-Sendfile

  • Grab the source
  • Compile and install – apxs -cia mod_xsendfile.c
  • Restart apache – apachectl -restart

See here for configuration details

Usage

if ($user->isLoggedIn())
{
    header("X-Sendfile: $path_to_somefile");
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"$somefile\"");
    exit;
}

Using X-Sendfile with the SonataMediaBundle.

/**
 * @Route("/delivery/{id}/{format}" , name="content-delivery")
 * @Template()
*/
public function deliveryAction($id,$format){
    $response =  new Response();
 
    //authenticate the user here
    $authenticated = ....
 
    if($authenticated){
        $media_mgr = $this->get("sonata.media.manager.media");
        $media = $media_mgr->findMediaBy(array("id"=>$id));
        $pool = $media_mgr->getPool();
        $provider = $pool->getProvider($media->getProviderName());
 
 
        $path = $provider->getCdn()->getPath(sprintf('%s/%s', $provider->generatePath($media), $media->getProviderReference()), true);
        $response->headers->set('Content-Type', $media->getContentType());
        $response->headers->set('X-Sendfile', __DIR__.'/../../../../web/'.$path);
 
        return $response;
    }
 
    $response->setContent("success:false");
    return $response;
}

Note: The SonataMediaBundle stores audio with the MIME type application/octet-stream to deliver this correct I had to set the content type to be audio/mpeg. This could have been due to the audio being captured on an iPhone and/or it being sent back down to iPhones.

Check out some of my other Symfony 2.0 posts,