通过open-uri加载url之后,如何处理生成的Tempfile对象?

时间:2018-05-23 16:34:48

标签: ruby url

我想知道如何从互联网下载图像然后在本地存储它们。 这就是我的所作所为:

require 'open-uri' # => true

file = open "https://s3-ap-southeast-1.amazonaws.com/xxx/Snip20180323_40.png"
# => #<Tempfile:/var/folders/k0/.../T/open-uri20180524-60756-1r44uix>

然后我对这个Tempfile对象感到困惑。我发现我可以通过以下方式获取原始网址:

file.base_uri
# => #<URI::HTTPS https://s3-ap-southeast-1.amazonaws.com/xxx/Snip20180323_40.png>

但是我找不到可以直接获取原始文件名Snip20180323_40.png的方法。

  1. 是否有可以直接从Tempfile对象获取原始文件名的方法?
  2. Tempfile对象主要用于什么目的?它们是否与普通文件对象不同,例如:file_object = File.open('how_old.rb') # => #<File:how_old.rb>
  3. 我可以将Tempfile对象转换为File对象吗?
  4. 如何将此Tempfile写为本地目录中的同名文件,例如/users/user_name/images/Snip20180323_40.png

1 个答案:

答案 0 :(得分:2)

  1. 原始文件名仅在URL中可用。只需uri.path.split("/").last
  2. Tempfiles是有效的文件,区别在于垃圾收集时,底层文件被删除。
  3. 您可以使用FileUtils.copy复制基础文件,也可以打开Tempfile,读取它,然后将其写入您选择的新文件句柄。
  4. 这样的事情应该有效:

    def download_url_to(url, base_path)
      uri = URI(url)
      filename = uri.path.split("/").last
      new_file = File.join(base_path, filename)
      response = uri.open
      open(new_file, "wb") {|fp| fp.puts response.read }
      return new_file
    end
    
  5. 值得注意的是,如果文件小于10kb,您将获得StringIO对象而不是Tempfile对象。上述解决方案处理两种情况。这也只接受路径参数的最后部分 - 它取决于你清理它,以及文件本身的内容;在大多数情况下,您不希望允许客户端将任意文件下载到您的系统。例如,您可能希望确保文件名不包含..\\..\\.."之类的路径,这些路径可用于将文件写入非预期位置。