【问题标题】:X-Sendfile, Rails & NginxX-Sendfile、Rails 和 Nginx
【发布时间】:2025-09-15 19:55:02
【问题描述】:

我对 X-Sendfile、NGinx 和 Rails 的问题感到沮丧。我已经阅读了几个文档和教程,但我就是不明白这一点。

无论我尝试什么,我都会得到 404。这是 NGINX 的 X-Sendfile 部分。

 location / {
                    proxy_set_header X-Sendfile-Type X-Accel-Redirect;
                    proxy_set_header X-Accel-Mapping /var/www/cube_storage/uploads/=/cdn;  #maps a real path to the internal location
                    ...
            } # end of location app

            location /cdn {
                    root /var/www/cube_storage/;
                    internal;
                    proxy_set_header X-Sendfile-Type X-Accel-Redirect;
                    proxy_set_header X-Accel-Mapping /var/www/cube_storage/=/cdn/;
                    }

在我的 rails 应用中启用了 X-Accel-Redirect:

config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx

这是负责提供文件的控制器的代码:

def image
@activity = AccountActivity.where(:id => params[:id]).first

if !@activity || !@activity.file_attachment_is_image? || @activity.file_attachment_name != requested_file_name()
  l = Logger.new("#{Rails.root}/logs/cdn_activity.log")
  l.info(params.inspect)

  render :file => "#{Rails.root}/public/404.html", :layout => false, :status => :not_found
else
  begin
    if !params[:version] || params[:version] == "original"
      t = @activity.file_attachment # thats the original image!
    else
      t = @activity.file_attachment.send(params[:version])
    end

    send_file t.current_path  ,:disposition => 'inline'
  rescue Exception => ex
    l = Logger.new("#{Rails.root}/logs/cdn_activity.log")
    l.info("--------------------------")
    l.info(Time.now.to_s)
    l.info("exception -> #{ex.message}")
    l.info("params: #{params.inspect}")
    render :file => "#{Rails.root}/public/404", :layout => false, :status => :not_found
  end

end

结束

我使用carrierwave作为存储引擎。也许有人只是看到了我的错误,但即使经过几个小时的尝试,我也没有看到。

还有一件事,该请求甚至没有显示在 development.log 中(是的,我也为 dev 激活了 X-Accel)。

问候,亚历克斯

【问题讨论】:

    标签: ruby-on-rails nginx carrierwave x-sendfile


    【解决方案1】:

    知道了:永远不要在你的 nginx 位置指令中使用任何 Rails 路由部分。有了这个,它就可以工作了:

    location / {
      proxy_set_header X-Sendfile-Type X-Accel-Redirect;
      # Maps a real path to the internal location
      proxy_set_header X-Accel-Mapping /var/www/cube_storage/uploads/=/downloads;  
    
    } # end of location app
    
    location /downloads {
      alias /var/www/cube_storage/uploads/;
      internal;
    }
    

    【讨论】: