如何从URL下载文件并将其保存在Rails中?

Alo*_*ain 189 ruby ruby-on-rails file-handling

我有一个图像的URL,我想在本地保存,以便我可以使用Paperclip为我的应用程序生成缩略图.下载和保存图像的最佳方法是什么?(我查看了ruby文件处理,但没有遇到任何问题.)

Lev*_*evi 306

试试这个:

require 'open-uri'
open('image.png', 'wb') do |file|
  file << open('http://example.com/image.png').read
end
Run Code Online (Sandbox Code Playgroud)

  • 这将读取内存中的整个文件.最好的方法是`IO.copy_stream(open('http://example.com/image.png'),'destination.png')` (67认同)
  • rails 5,2016,我不需要'require'open-uri'`,只是使用它下面的代码 (3认同)
  • 这个答案对我不起作用。正确答案在这里:http://stackoverflow.com/a/29743394/1536309 (2认同)

Cle*_*elm 133

更短的版本:

require 'open-uri'
download = open('http://example.com/image.png')
IO.copy_stream(download, '~/image.png')
Run Code Online (Sandbox Code Playgroud)

要保持相同的文件名:

IO.copy_stream(download, "~/#{download.base_uri.to_s.split('/')[-1]}")
Run Code Online (Sandbox Code Playgroud)

  • 并且更高效,因为输出不作为字符串存储在内存中。+1 (3认同)
  • 虽然显示两个答案实际上很有用,但像我这样的人可以同时看到两者,考虑差异,然后出于正确的原因有意识地选择这个答案:) (3认同)
  • 使用“open”时,我收到来自 Rubocop 的安全警告。我将其替换为“URI.parse(url).open”。在这里阅读有关该警察的更多信息:https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Security/Open (2认同)
  • 纯粹的“open”对我不起作用,必须使用“URI.open” (2认同)

sup*_*ary 29

如果您正在使用PaperClip,则现在可以自动处理从URL下载.

假设你有类似的东西:

class MyModel < ActiveRecord::Base
  has_attached_file :image, ...
end
Run Code Online (Sandbox Code Playgroud)

在你的模型上,只需将图像指定为URL,就像这样(用有意的手写):

@my_model = MyModel.new
image_url = params[:image_url]
@my_model.image = URI.parse(image_url)
Run Code Online (Sandbox Code Playgroud)

您可能希望将其放在模型中的方法中.这对Heroku的临时文件系统也可以正常工作.

Paperclip将从那里拿走它.

来源:回形针文档

  • 对于未来的搜索者,Paperclip默认不再允许这样做:https://medium.com/in-the-weeds/all-about-paperclips-cve-2017-0889-server-side-request-forgery-ssrf-vulnerability- 8cb2b1c96fe8 (3认同)

use*_*745 13

可能是最简单的方法:

require 'open-uri'
image_url = "https://i.imgur.com/ZWnhY9T.png"
IO.copy_stream(URI.open(image_url), 'destination.png')
Run Code Online (Sandbox Code Playgroud)


Sag*_*oss 12

我认为这是最明确的方式:

require 'open-uri'

File.write 'image.png', open('http://example.com/image.png').read
Run Code Online (Sandbox Code Playgroud)


Pär*_*der 8

查看标准库中的Net :: HTTP.该文档提供了有关如何使用HTTP下载文档的几个示例.

  • 这个答案需要更多的可见性,因为`Kernel#open`不仅使文件访问成为可能,而且还通过在管道符号前加前缀来处理调用(例如,`open(“ | ls”)`)。因此,通过对“ Kernel#open”的参数使用变量输入,可能会导致严重的安全风险。 (2认同)