Nginx + Rails + 发送文件:找不到文件
Nginx + Rails + sendfile : file not found
最近在为 nginx+rails 设置发送文件时遇到问题。我们有一种文件下载已经由 nginx 处理,我们想添加第二个规则来处理另一个位置的另一种文件,但到目前为止我们没有成功。
Ruby 控制器:
def download_file
send_file("/srv/www/myapp/shared/tmp/directory/file.zip")
end
环境配置文件:
Rails.application.configure do
# ..
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
# ..
end
Nginx 配置:
upstream myapp {
server 127.0.0.1:9292;
}
server {
listen 80;
server_name myapp.tld;
client_max_body_size 10M;
root /srv/www/myapp/current/public;
# This first block works perfectly
location /__working_file {
internal;
alias /var/lib/myapp;
}
# This second block does not work at all
location /__new_files {
internal;
alias /srv/www/myapp/shared/tmp/directory;
}
location / {
root /srv/www/myapp/current/public;
try_files $uri @app;
}
location @app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
# This first rule works perfectly
proxy_set_header X-Accel-Mapping /var/lib/myapp/=/__working_file/;
# This second rule doesn't
proxy_set_header X-Accel-Mapping /srv/www/myapp/shared/tmp/directory/=/__new_files/;
proxy_pass_header Server;
proxy_read_timeout 300;
proxy_pass http://myapp;
}
}
结果
当访问控制器操作时,send_file
命令被触发,然后我们在浏览器中得到一个 "File not found",没有下载任何东西,rails 日志显示:
Sent file /srv/www/myapp/shared/tmp/directory/file.zip (0.4ms)
Completed 200 OK in 169ms (ActiveRecord: 37.5ms)
Started GET "/srv/www/myapp/shared/tmp/directory/file.zip" for 109.190.197.126 at 2018-11-20 11:34:44 +0100
ActionController::RoutingError (No route matches [GET] "/srv/www/myapp/shared/tmp/directory/file.zip"):
该文件确实存在并且可读,但 nginx 似乎无法访问它。有什么想法吗?
在路由时它没有得到。你必须提供正确的上班路线。
问题出在两个X-Accel-Mapping
的设置方式上。 Rack
确实可以处理自this PR #1187合并后的几个映射。
不过到今天为止,这个PR已经合并到master上了,还没有发布(2.0.6目前是最新的版本).
唯一的问题是,设置多个映射的正确方法是使用一个 proxy_set_header
规则,并用逗号分隔每个映射,如下所示:
proxy_set_header X-Accel-Mapping, /var/lib/myapp/=/__working_file/,/srv/www/myapp/shared/tmp/directory/=/__new_files/
最近在为 nginx+rails 设置发送文件时遇到问题。我们有一种文件下载已经由 nginx 处理,我们想添加第二个规则来处理另一个位置的另一种文件,但到目前为止我们没有成功。
Ruby 控制器:
def download_file
send_file("/srv/www/myapp/shared/tmp/directory/file.zip")
end
环境配置文件:
Rails.application.configure do
# ..
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
# ..
end
Nginx 配置:
upstream myapp {
server 127.0.0.1:9292;
}
server {
listen 80;
server_name myapp.tld;
client_max_body_size 10M;
root /srv/www/myapp/current/public;
# This first block works perfectly
location /__working_file {
internal;
alias /var/lib/myapp;
}
# This second block does not work at all
location /__new_files {
internal;
alias /srv/www/myapp/shared/tmp/directory;
}
location / {
root /srv/www/myapp/current/public;
try_files $uri @app;
}
location @app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
# This first rule works perfectly
proxy_set_header X-Accel-Mapping /var/lib/myapp/=/__working_file/;
# This second rule doesn't
proxy_set_header X-Accel-Mapping /srv/www/myapp/shared/tmp/directory/=/__new_files/;
proxy_pass_header Server;
proxy_read_timeout 300;
proxy_pass http://myapp;
}
}
结果
当访问控制器操作时,send_file
命令被触发,然后我们在浏览器中得到一个 "File not found",没有下载任何东西,rails 日志显示:
Sent file /srv/www/myapp/shared/tmp/directory/file.zip (0.4ms)
Completed 200 OK in 169ms (ActiveRecord: 37.5ms)
Started GET "/srv/www/myapp/shared/tmp/directory/file.zip" for 109.190.197.126 at 2018-11-20 11:34:44 +0100
ActionController::RoutingError (No route matches [GET] "/srv/www/myapp/shared/tmp/directory/file.zip"):
该文件确实存在并且可读,但 nginx 似乎无法访问它。有什么想法吗?
在路由时它没有得到。你必须提供正确的上班路线。
问题出在两个X-Accel-Mapping
的设置方式上。 Rack
确实可以处理自this PR #1187合并后的几个映射。
不过到今天为止,这个PR已经合并到master上了,还没有发布(2.0.6目前是最新的版本).
唯一的问题是,设置多个映射的正确方法是使用一个 proxy_set_header
规则,并用逗号分隔每个映射,如下所示:
proxy_set_header X-Accel-Mapping, /var/lib/myapp/=/__working_file/,/srv/www/myapp/shared/tmp/directory/=/__new_files/