Symfony - 如何使用nginx的X-Accel-Redirect从控制器提供图像

时间:2017-03-05 23:14:59

标签: nginx symfony

我想仅向授权用户提供受保护的图像。因此,我在控制器中使用import UIKit import Google import GoogleSignIn @UIApplicationMain // [START appdelegate_interfaces] class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate { // [END appdelegate_interfaces] var window: UIWindow? // [START didfinishlaunching] func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Initialize sign-in var configureError: NSError? GGLContext.sharedInstance().configureWithError(&configureError) assert(configureError == nil, "Error configuring Google services: \(configureError)") GIDSignIn.sharedInstance().delegate = self return true } // [END didfinishlaunching] // [START openurl] func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool { return GIDSignIn.sharedInstance().handle(url, sourceApplication: sourceApplication, annotation: annotation) } // [END openurl] @available(iOS 9.0, *) func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool { return GIDSignIn.sharedInstance().handle(url, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String, annotation: options[UIApplicationOpenURLOptionsKey.annotation]) } // [START signin_handler] func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) { if let error = error { print("\(error.localizedDescription)") // [START_EXCLUDE silent] NotificationCenter.default.post( name: Notification.Name(rawValue: "ToggleAuthUINotification"), object: nil, userInfo: nil) // [END_EXCLUDE] } else { // Perform any operations on signed in user here. let userId = user.userID // For client-side use only! let idToken = user.authentication.idToken // Safe to send to the server let fullName = user.profile.name let givenName = user.profile.givenName let familyName = user.profile.familyName let email = user.profile.email // [START_EXCLUDE] NotificationCenter.default.post( name: Notification.Name(rawValue: "ToggleAuthUINotification"), object: nil, userInfo: ["statusText": "Signed in user:\n\(fullName)"]) // [END_EXCLUDE] } } // [END signin_handler] // [START disconnect_handler] func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!) { // Perform any operations when the user disconnects from app here. // [START_EXCLUDE] NotificationCenter.default.post( name: Notification.Name(rawValue: "ToggleAuthUINotification"), object: nil, userInfo: ["statusText": "User has disconnected."]) // [END_EXCLUDE] } // [END disconnect_handler] } ,它工作正常。但是,我想使用Nginx的XSendfile(X-Accel-Redirect)。我已经按照Nginx的documantation中的说明完成了相同的步骤。

此外,我已将BinaryFileResponse添加到控制器。但是现在我一直在回复404。

以下是我的配置和代码:

Nginx的:

BinaryFileResponse::trustXSendfileTypeHeader();

Symfony Controller:

server {
    listen 80;
    listen 443 ssl http2;
    server_name symfony.app;
    root "/home/vagrant/Sites/Symfony/web";

    index index.html index.htm index.php app.php app_dev.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /app.php?$query_string;
    }

    location /images/ {
        internal;
        alias   /home/vagrant/Sites/Symfony/app/media/images/listings/4/;
    }

    client_max_body_size 100m; 

    # DEV
    location ~ ^/(app_dev|app_test|config)\.php(/|$) {
        #fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;  # allows trailing slash after app_dev.php/
        fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_intercept_errors off;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
    }

    # PROD
    location ~ ^/app\.php(/|$) {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_intercept_errors off;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
        internal;
    }

    location ~ /\.ht {
        deny all;
    }

    ssl_certificate     /etc/nginx/ssl/symfony.app.crt;
    ssl_certificate_key /etc/nginx/ssl/symfony.app.key;
}

所以,去 http://symfony.app/images/1.jpg 应该返回一张图片,但是得到了一张图片。

1 个答案:

答案 0 :(得分:1)

/images/位置标记为内部,因此无法访问来自浏览器的外部请求。 http://nginx.org/en/docs/http/ngx_http_core_module.html#internal

我认为getPictureAction的路径路径是/images/{id},并且无法访问它,因为nginx具有内部相同位置/images/并返回404错误。

将nginx位置重命名为/images-internal/

location /images-internal/ {
    internal;
    alias   /home/vagrant/Sites/Symfony/app/media/images/listings/4/;
}

将php代码更改为:

public function getPictureAction(Request $request, $id)
{
    $dir = $this->get('kernel')->getRootDir() . '/' . 'media/images/listings/4/';
    $path = $dir . $id;

    $request->headers->set('X-Sendfile-Type', 'X-Accel-Redirect');
    $request->headers->set('X-Accel-Mapping', $dir . '=/images-internal/');

    BinaryFileResponse::trustXSendfileTypeHeader();

    $response = new BinaryFileResponse($path);

    $response->headers->set('Content-Type', 'image/jpg');
    $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE);

    return $response;
}