在 Ruby 中下载文件,重定向到带有空格的 URL

mrt*_*mrt 3 ruby open-uri

我正在尝试下载一组图像,并提供它们的 URL。某些 URL 重定向到包含空格的 URL,这会导致 OpenURI 引发错误。

即我提供了http://www.example.com/upload/comercial%20(2).jpg重定向到https://www.example.com/upload/comercial (2).jpg. 这会在负责下载的代码中引发错误:

url = 'http://www.example.com/upload/comercial%20(2).jpg'
download = open(url, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE, allow_redirections: :all})

OpenURI::HTTPError: 302 Redirect (Invalid Location URI)
Run Code Online (Sandbox Code Playgroud)

有没有办法让 OpenURI 理解重定向?

观察: 在对空格进行编码后,OpenURI 可以正确处理生成的重定向 URL,如下所示:

redirected = 'https://www.example.com/upload/comercial (2).jpg'
encoded = URI.escape(redirected) 
# https://www.example.com/upload/comercial%20(2).jpg

download = open(encoded, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE, allow_redirections: :all})
# Success
Run Code Online (Sandbox Code Playgroud)

显然,在调用之前,重定向 URL 是未知的open()

Ser*_*sev 5

您可以做的是手动处理重定向,通过使用redirect: false选项并从重定向异常中拯救(当 open-uri 收到重定向响应并且不允许执行它时会引发该异常)。然后对 url 进行编码并重试。像这样的东西:

begin
  open(uri, redirect: false)
rescue OpenURI::HTTPRedirect => redirect
  uri = redirect.uri # assigned from the "Location" response header
  escaped = URI.escape(redirected) 
  open(escaped, redirect: false)
end
Run Code Online (Sandbox Code Playgroud)

您可以将此逻辑隐藏在方法中,并且对其调用者来说这将是“一次调用”。抽象性很好。