Сохранить изображение из URL-адреса скрепкой

Ответы:

154

Вот простой способ:

require "open-uri"

class User < ActiveRecord::Base
  has_attached_file :picture

  def picture_from_url(url)
    self.picture = open(url)
  end
end

Тогда просто:

user.picture_from_url "http://www.google.com/images/logos/ps_logo2.png"
Николя Бланко
источник
7
Если вам нужно использовать, например, update_attributesпереименование picture_from_urlв picture_url=(value).
Daniel Rikowski 02
3
Это потенциально небезопасно, потому что пользователь может позвонить user.picture_from_url('/etc/password'). Хотя, вероятно, в большинстве ситуаций это нормально.
Дэвид Туйт
1
В целях безопасности вам следует занести схему URI в белый список, а частные хосты
Джон Даутат,
3
См. Ответ ниже, чтобы найти еще лучшее решение.
geekazoid
6
Использование open(url), имя файла является неточным, например, open-uri20150106-10034-lpd5fm.вместо ef3a601e_ef3d008b_ef3d0f7e.jpg.
Джошуа Пинтер
196

В Paperclip 3.1.4 это стало еще проще.

def picture_from_url(url)
  self.picture = URI.parse(url)
end

Это немного лучше, чем open (url). Потому что с open (url) вы получите в качестве имени файла "stringio.txt". С помощью приведенного выше вы получите собственное имя файла на основе URL-адреса. т.е.

self.picture = URI.parse("http://something.com/blah/avatar.png")

self.picture_file_name    # => "avatar.png"
self.picture_content_type # => "image/png"
Адитья Санги
источник
3
Из вики со скрепками : github.com/oughttbot/paperclip/wiki/ ... Я успешно запустил его в консоли, приложение находится в героку.
Донни Курния
3
FYI, для S3 URLs я все еще получаю application/octet_streamкак content_type.
Джошуа Пинтер
5
Если вы все еще используете скрепку после того, как она устарела, вам может потребоваться также обеспечить загрузку загрузчика ввода-вывода URI: Paperclip :: UriAdapter.register (в конфигурации или временно через консоль, если это все, что вам нужно)
Msencenb
Подход правильный, но в последней версии синтаксис изменен! Посмотрите мой ответ ниже => stackoverflow.com/a/56039191/3182171
Диего Д.
Вам нужно добавить запись в инициализаторе github.com/gotitbot/paperclip/wiki/…
ianpetzer
16

У меня это не сработало, пока я не использовал "open" для разобранного URI. как только я добавил "открыть", все заработало!

def picture_from_url(url)
  self.picture = URI.parse(url).open
end

Моя версия скрепки - 4.2.1

Перед открытием он не мог правильно определить тип контента, потому что это не был файл. Он сказал бы image_content_type: "binary / octet-stream", и даже если бы я переопределил его правильным типом содержимого, это не сработало бы.

Микаэль Макаров
источник
Спасибо за это! Именно то, чего мне не хватало.
Дэн
Если вы сделаете это, вы потеряете свое расширение. Вам нужен Paperclip :: UriAdapter.register в инициализаторе ... тогда вам не нужно .open в конце. См github.com/thoughtbot/paperclip/wiki/...
ianpetzer
15

Сначала загрузите изображение с curbдрагоценным камнем в a, TempFileа затем просто назначьте объект временного файла и сохраните свою модель.

Ariejan
источник
2
Я не вижу, что не так с этим ответом, голосую "за", потому что вижу "против".
jpemberthy
Это самый эффективный ответ ( безусловно ). Я не особо разбираюсь в производительности, но это действительно складывается, если вы работаете с большими файлами.
Чип
3

Это может быть вам полезно. Вот код с использованием скрепки и изображения в удаленном URL-адресе.

require 'rubygems'
require 'open-uri'
require 'paperclip'
model.update_attribute(:photo,open(website_vehicle.image_url))

В модели

class Model < ActiveRecord::Base
  has_attached_file :photo, :styles => { :small => "150x150>", :thumb => "75x75>" }
end
Prabu
источник
3

Поскольку это старые ответы, вот и новый:

Добавьте удаленный URL-адрес изображения на желаемый контроллер в базе данных

$ rails generate migration AddImageRemoteUrlToYour_Controller image_remote_url:string
$ rake db:migrate

Отредактируйте вашу модель

attr_accessible :description, :image, :image_remote_url
.
.
.
def image_remote_url=(url_value)
  self.image = URI.parse(url_value) unless url_value.blank?
  super
end

* В Rails4 вам нужно добавить attr_accessible в Контроллер.

Обновите свою форму, если вы разрешаете другим загружать изображение с URL-адреса

<%= f.input :image_remote_url, label: "Enter a URL" %>
Мини Джон
источник
для чего super?
Теренс Чоу
Функция superиспользуется для вызова исходного метода, поиск тела метода начинается в суперклассе объекта, который, как было обнаружено, содержит исходный метод
Mini John
2

Это хардкорный метод:

original_url = url.gsub(/\?.*$/, '')
filename = original_url.gsub(/^.*\//, '')
extension = File.extname(filename)

temp_images = Magick::Image.from_blob open(url).read
temp_images[0].write(url = "/tmp/#{Uuid.uuid}#{extension}")

self.file = File.open(url)

где Uuid.uuid просто создает случайный идентификатор.

Мартин Штрайхер
источник
2

В официальной документации сообщается здесь https://github.com/gotitbot/paperclip/wiki/Attachment-downloaded-from-a-URL

В любом случае он кажется не обновленным, потому что в последней версии скрепки что-то изменилось, и эта строка кода больше не действительна:

user.picture = URI.parse(url)

Это вызывает ошибку, в частности, возникает эта ошибка:

Paperclip::AdapterRegistry::NoHandlerError: No handler found for #<URI:: ...

Новый правильный синтаксис:

url = "https://www.example.com/photo.jpeg"
user.picture = Paperclip.io_adapters.for(URI.parse(url).to_s, { hash_digest: Digest::MD5 })

Также нам нужно добавить эти строки в файл config / initializers / paperclip.rb :

Paperclip::DataUriAdapter.register
Paperclip::HttpUrlProxyAdapter.register

Протестировал это с версией скрепки, 5.3.0и она работает.

Диего Д.
источник
Спасибо за это - конфигурационный материал исправил это для меня (Paperclip v6.1.0)
Owlvark