如何使用 rails 活动存储从 url 保存图像?
How to save an image from a url with rails active storage?
我正在寻找使用 rails 5.2 活动存储保存位于另一个 http 网络服务器上的文件(在本例中为图像)。
我有一个带有源 url 字符串参数的对象。然后在 before_save 我想抓取远程图像并保存它。
示例:URL 图像 http://www.example.com/image.jpg。
require 'open-uri'
class User < ApplicationRecord
has_one_attached :avatar
before_save :grab_image
def grab_image
#this indicates what I want to do but doesn't work
downloaded_image = open("http://www.example.com/image.jpg")
self.avatar.attach(downloaded_image)
end
end
提前感谢您的任何建议。
刚刚找到了我自己的问题的答案。我的第一直觉非常接近...
require 'open-uri'
class User < ApplicationRecord
has_one_attached :avatar
before_save :grab_image
def grab_image
downloaded_image = open("http://www.example.com/image.jpg")
self.avatar.attach(io: downloaded_image , filename: "foo.jpg")
end
end
更新:请注意下面的评论,“你必须小心不要将用户输入传递给打开,它可以执行任意代码,例如 open("|date")"
无需明确输入文件名即可执行此操作的最简单方法是:
url = URI.parse("https://your-url.com/abc.mp3")
filename = File.basename(url.path)
file = URI.open(url)
user = User.first
user.avatar.attach(io: file, filename: filename)
这会自动保存针对该特定用户对象的头像。
如果您使用像 S3 这样的远程服务,可以通过以下方式检索 URL:
user.avatar.service_url
使用 down
gem 避免使用 open-uri:
的安全问题
image = Down.download(image_url)
user.image.attach(io: image, filename: "image.jpg")
正如评论中所说,使用open
或URI.open
是非常危险的,因为它不仅可以访问文件,还可以通过前缀管道符号处理调用(例如open("| ls")
).
Kernel#open
and URI.open
enable not only file access but also process invocation by prefixing a pipe symbol (e.g., open("| ls")
). So, it may lead to a serious security risk by using variable input to the argument of Kernel#open
and URI.open
. It would be better to use File.open
, IO.popen
or URI.parse#open
explicitly.
摘自 Rubocop 文档:https://docs.rubocop.org/rubocop/1.8/cops_security.html#securityopen
因此,更安全的解决方案是:
class User < ApplicationRecord
has_one_attached :avatar
before_save :grab_image
def grab_image
downloaded_image = URI.parse("http://www.example.com/image.jpg").open
avatar.attach(io: downloaded_image, filename: "foo.jpg")
end
end
我正在寻找使用 rails 5.2 活动存储保存位于另一个 http 网络服务器上的文件(在本例中为图像)。
我有一个带有源 url 字符串参数的对象。然后在 before_save 我想抓取远程图像并保存它。
示例:URL 图像 http://www.example.com/image.jpg。
require 'open-uri'
class User < ApplicationRecord
has_one_attached :avatar
before_save :grab_image
def grab_image
#this indicates what I want to do but doesn't work
downloaded_image = open("http://www.example.com/image.jpg")
self.avatar.attach(downloaded_image)
end
end
提前感谢您的任何建议。
刚刚找到了我自己的问题的答案。我的第一直觉非常接近...
require 'open-uri'
class User < ApplicationRecord
has_one_attached :avatar
before_save :grab_image
def grab_image
downloaded_image = open("http://www.example.com/image.jpg")
self.avatar.attach(io: downloaded_image , filename: "foo.jpg")
end
end
更新:请注意下面的评论,“你必须小心不要将用户输入传递给打开,它可以执行任意代码,例如 open("|date")"
无需明确输入文件名即可执行此操作的最简单方法是:
url = URI.parse("https://your-url.com/abc.mp3")
filename = File.basename(url.path)
file = URI.open(url)
user = User.first
user.avatar.attach(io: file, filename: filename)
这会自动保存针对该特定用户对象的头像。
如果您使用像 S3 这样的远程服务,可以通过以下方式检索 URL:
user.avatar.service_url
使用 down
gem 避免使用 open-uri:
image = Down.download(image_url)
user.image.attach(io: image, filename: "image.jpg")
正如评论中所说,使用open
或URI.open
是非常危险的,因为它不仅可以访问文件,还可以通过前缀管道符号处理调用(例如open("| ls")
).
Kernel#open
andURI.open
enable not only file access but also process invocation by prefixing a pipe symbol (e.g.,open("| ls")
). So, it may lead to a serious security risk by using variable input to the argument ofKernel#open
andURI.open
. It would be better to useFile.open
,IO.popen
orURI.parse#open
explicitly.
摘自 Rubocop 文档:https://docs.rubocop.org/rubocop/1.8/cops_security.html#securityopen
因此,更安全的解决方案是:
class User < ApplicationRecord
has_one_attached :avatar
before_save :grab_image
def grab_image
downloaded_image = URI.parse("http://www.example.com/image.jpg").open
avatar.attach(io: downloaded_image, filename: "foo.jpg")
end
end