Sometimes we need to serve files directly from application, especially when file access is restricted by account permissions. Using readfile() to achieve this can successfully kill our web server – even without huge load.

To avoid performance problems we can use nginx X-Accel-Redirect feature, and serve files from application through nginx server.

Example: Serving gallery photos

Configure nginx
We have to configure new location, and define it as internal.

location /gallery/ {
  internal;
  root   /absolute/path;
}

Gallery files should be located in /absolute/path/gallery, so example image should be located in /absolute/path/gallery/EXAMPLEIMAGE_FILEBASENAME.JPG
Serve file
Now we can do whatever we want before sending file to user. I prepare little example, to show what can be done.

# /gallery/getimage/3
$image = new Image($this->request->getParam('id'));
$user = $this->getLoggedUser();
 
header('Content-type: image/jpeg');
if ($user->hasRight($image)) {
    header("X-Accel-Redirect: /gallery/".$image->getFilename());
} else {
    header("X-Accel-Redirect: /gallery/".self::DEFAULT_IMAGE_FILENAME);
}

So if user has right to see gallery image, will get it. Otherwise default image is served. Serving files now is safe, efficient and really straightforward.

More information about X-Accel-Redirect can be found here

8 Responses to “Efficient file serving in PHP application with nginx”

  1. Ryan says:

    Nice tip, thx

  2. Ian says:

    That’s pretty handy! Too bad there isn’t a similar feature in Apache.

  3. David Hollis says:

    So if a user doesn’t have rights to the image but happens to know the filename under /gallery, they can just access it directly?

    • Slawek Lukasiewicz says:

      @David

      No, because you cant get file directly from location set as internal.

      According to nginx documentation: “The location should be defined as internal; to prevent the client from going directly to the URI. “

  4. huarong says:

    Gallery files should be located in /absolute/path/gallery, so example image should be located in /absolute/path/gallery/EXAMPLEIMAGE_FILEBASENAME.JPG

    /absolute/path

    /absolute/path/EXAMPLEIMAGE_FILEBASENAME.JPG

    http://www.xxx.com/gallery/EXAMPLEIMAGE_FILEBASENAME.JPG

  5. [...] Efficient file serving in PHP application with nginx [...]

Leave a Reply →