使用Sinatra提供单个图像,无论请求的是什么。

3
我正在使用Sinatra服务一张图片,但是当你请求这张图片时,我希望Sinatra提供另一张图片。因此,每次在服务器上请求图片时,都会返回一张静态图片。
%w[sintra].each{|gem| require gem}

# <img src="https://www.mywebsite.com/1234.png">
# <img src="https://www.mywebsite.com/abcd.png">

get '/:image' do 
 image = params[:image].split(".")[0]
 # image = 1234

 if image == key 
  #do stuff
 else
  #do other stuff
 end

 #this is where I'm having a problem
 special_code_that_replaces_1234.png = "static_image_on_server.png"
 #so sinatra should return "static_image_on_server.png" no matter what image is asked for. 

end

我已经仔细阅读了Sinatra的文档,具体来说是这个:http://www.sinatrarb.com/intro.html#Accessing%20the%20Request%20Object。可能我没找对部分,具体是"触发另一个路由"。我感觉自己转圈了。
我的应用程序确实有一个"public"目录,里面有"static_image_on_server.png"。

将路径切换为 get '/*.*' 是否更好?您可能希望确保所有图像都在 /images 中,以使此映射更具体。 - tadman
数据的输入方式是任意的。我无法在其位置注入另一张图片。或者我不明白有人怎么能做到。 - user2446058
啊,如果您无法控制传入路由,则需要使用通配符路由。 - tadman
当然,将来会有一个验证。我没有想到那个。听起来有点突兀。我正在使用ProxyPass在我的Apache配置中允许多个Sinatra应用程序。你能否发布一个关于你上面评论的示例/文档的链接? - user2446058
2个回答

3
假设您有一个目录public/imgs,其中存储了您的图像:

使用redirect()函数:

require 'sinatra'

get "/imgs/*.*" do
  img_name, ext = params[:splat]

  if image_name == key 
    #do stuff
  else
    #do other stuff
  end

  redirect to('/imgs/alien1.png')
end

默认情况下,Sinatra 会首先检查所请求的文件是否在./public 文件夹中,并在存在时返回它。如果文件不在 ./public 中,则 Sinatra 将尝试匹配路由。因此,路由中的代码无法阻止用户查看 public 文件夹中现有的图像。
您可以在路由文件的顶部添加 disable :static 来停止 Sinatra 查找所请求的文件。相反,Sinatra 将直接进行路由匹配。在这种情况下,在示例中使用的 redirect() 会导致无限循环。因此,如果您有 public 文件夹中不想让用户看到的图片,则不能使用 redirect()。
通过 send_file():
看起来 tadman 的 send_file() 解决方案需要一个绝对(或相对)的文件系统路径,因此您可以执行以下操作:
require 'sinatra'

get "/imgs/*.*" do
  img_name, ext = params[:splat]

  if image_name == key 
    #do stuff
  else
    #do other stuff
  end

  send_file File.expand_path('imgs/alien1.png', settings.public_folder)
end

请注意,使用send_file()方法时,浏览器将继续显示最初请求的图像的原始url,这可能是你想要的,也可能不是。

就是这样。我只需要重定向。非常感谢。 - user2446058
@user2446058,嗯...现在我发了这个,我想知道为什么它不会导致无限循环? - 7stud
1
@user2446058,看起来send_file()需要一个绝对的文件系统路径,所以我添加了一个如何让send_file()工作的示例。 - 7stud
@user2446058,默认情况下,Sinatra会首先检查所请求的文件是否在./public文件夹中,并在存在时返回该文件。如果文件不在./public中,则Sinatra将尝试匹配路由。如果我将"disable:static"添加到文件顶部,那么Sinatra就不会在./public中查找文件,而是直接进入路由匹配。在这种情况下,我的解决方案将导致无限循环。因此,如果您在公共文件夹中有不想让用户看到的图像,则不能使用redirect()。 - 7stud

1
通常情况下,这样处理:

Normally this is handled like this:

get '/*.*' do
 # ... Your code ...

 # Send static file.
 send_file 'static_image_on_server.png'
end

我创建了一个新的路由,匹配你上面的代码,但是我得到了一个404错误,原始图片被要求。我也注释掉了我的代码。 - user2446058
你的Sinatra日志里有什么吗? - tadman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接