Обслуживание защищенных файлов с помощью Symfony2 и Nginx X-accel-redirect

Мой конфиг php-fpm 5.4 с nginx. Мне нужно обслуживать некоторые защищенные файлы. Поэтому я проверяю с Symfony, есть ли у пользователя правильные права, и затем я бы хотел, чтобы nginx обслуживал файл (swf), используя заголовок X-accel-redirect.

Контроллер в Symfony:

/**
 * @Route("/protected/swf")
 */
public function sendFileAction()
{
    // [...]    

    // user rights are ok, serve the file

    $fileName = 'myfile.swf';
    $filePath = $this->get('kernel')->getRootDir() . '/../files/' . $fileName;

    $response = new BinaryFileResponse($filePath);
    $response->trustXSendfileTypeHeader();
    return $response;
}

И мой конфиг nginx: ( http://wiki.nginx.org/XSendfile). Файлы находятся в каталоге за пределами веб-каталога (файлы).

location /files/ {
     internal;
     root   /path/to/folder;
}

Это работает (я имею в виду файл обслуживается), но я не думаю, что он использует XSendfile. Если я правильно понимаю, nginx будет обслуживать файл, если заголовок

X-Accel-Redirect: /files/myfile.swf;

настоящее. Но BinaryFileResponse использует путь на диске для поиска моего файла и не знает, что этот заголовок должен быть установлен, как указано выше.

Может кто-нибудь показать мне пример того, как это сделать? Спасибо!

2 ответа

Итак, я прочитал исходный код BinaryFileResponse, чтобы попытаться выяснить, как действовать дальше. Я думаю, что понял, но кто-нибудь может подтвердить, что это правильно? По крайней мере, кажется, работает как ожидалось.

Файлы, которые я хочу обслуживать, находятся в каталоге с именем private-dir вне корня документа.

Идея состоит в том, чтобы изменить запрос, чтобы nginx знал о сопоставлениях:

Мой новый контроллер:

/**
 * @Route("/protected/swf")
 */
public function sendFileAction()
{
    // [...]    
    // user rights are ok, serve the file

    $fileName = 'myfile.swf';
    $filePath = $this->get('kernel')->getRootDir() . '/../private-dir/' . $fileName;

    $this->getRequest()->headers->set('X-Sendfile-Type', 'X-Accel-Redirect');
    $this->getRequest()->headers->set('X-Accel-Mapping', '/private_dir/=/path/to/private-dir');

    BinaryFileResponse::trustXSendfileTypeHeader();
    $response = new BinaryFileResponse($filePath);
    return $response;
}

Позже BinaryFileResponse проанализирует эти заголовки, чтобы заменить реальный путь файла к частному URI, как это показано на веб-сайте nginx conf:

location /private_dir {
    alias /path/to/private-dir;
    internal;
}

Я делаю то же самое (проверяю разрешение пользователя и затем обслуживаю файлы из корня документа), но я не сделал это, используя BinaryFileResponse раньше, поэтому этот ответ может быть не тем, что вы ищете.

То, как я делаю это с IgorwFileServeBundle,

При этом вы будете использовать конфиг, как..

igorw_file_serve:
    factory: sendfile
    base_dir: $kernel.root_dir%/../files

А затем сервер файлы, как..

return $this->get('igorw_file_serve.response_factory')->create(
    $filePath,      // Relative to the base_dir
    $fileMimeType,
    array(
        'serve_filename'    => $fileName,
        'inline'            => false,
    )
);
Другие вопросы по тегам