Guardar la imagen de la URL con un clip

Respuestas:

154

He aquí una forma sencilla:

require "open-uri"

class User < ActiveRecord::Base
  has_attached_file :picture

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

Entonces simplemente:

user.picture_from_url "http://www.google.com/images/logos/ps_logo2.png"
Nicolás Blanco
fuente
7
Si necesita update_attributescambiar el nombre picture_from_urla, picture_url=(value)por ejemplo.
Daniel Rikowski
3
Esto es potencialmente inseguro porque un usuario podría llamar user.picture_from_url('/etc/password'). Sin embargo, probablemente esté bien en la mayoría de las situaciones.
David Tuite
1
Por seguridad, debe incluir en la lista blanca el esquema del URI y los hosts privados en la lista negra
John Douthat
3
Consulte la respuesta a continuación para obtener una solución aún mejor.
geekazoid
6
Usando open(url), el nombre del archivo no es exacto, por ejemplo, en open-uri20150106-10034-lpd5fm.lugar de ef3a601e_ef3d008b_ef3d0f7e.jpg.
Joshua Pinter
196

En Paperclip 3.1.4 se ha vuelto aún más sencillo.

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

Esto es un poco mejor que abierto (url). Porque con open (url) obtendrás "stringio.txt" como nombre de archivo. Con lo anterior, obtendrá un nombre adecuado del archivo según la URL. es decir

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

self.picture_file_name    # => "avatar.png"
self.picture_content_type # => "image/png"
Aditya Sanghi
fuente
3
Desde paperclip wiki: github.com/thoughtbot/paperclip/wiki/… Lo ejecuté con éxito en la consola, la aplicación está en heroku.
Donny Kurnia
3
Para su información, para las URL de S3 todavía obtengo application/octet_streamcomo content_type.
Joshua Pinter
5
Si todavía está usando un clip después de su desaprobación, es posible que también deba asegurarse de que se cargue el cargador de E / S de URI: Paperclip :: UriAdapter.register (en la configuración, o temporalmente a través de la consola si eso es todo lo que necesita)
Msencenb
¡El enfoque es correcto pero en la última versión se cambia la sintaxis! Mira mi respuesta a continuación => stackoverflow.com/a/56039191/3182171
Diego D
Debe
ianpetzer
16

No funcionó para mí hasta que usé "abierto" para el URI analizado. una vez que agregué "abrir" ¡funcionó!

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

La versión de mi clip es 4.2.1

Antes de abrir, no detectaría el tipo de contenido correcto, porque no era un archivo. Diría image_content_type: "binary / octet-stream", e incluso si lo anulo con el tipo de contenido correcto, no funcionaría.

Mïchael Makaröv
fuente
¡Gracias por esto! Exactamente lo que me estaba perdiendo.
Dan
Perderá su exención si hace esto. Necesita Paperclip :: UriAdapter.register en el inicializador ... entonces no necesita .open al final. Ver github.com/thoughtbot/paperclip/wiki/…
ianpetzer
15

Primero descargue la imagen con la curbgema a a TempFiley luego simplemente asigne el objeto del archivo temporal y guarde su modelo.

Ariejan
fuente
2
No veo qué hay de malo en esta respuesta, votarla porque veo una votación en contra.
jpemberthy
Esta es la respuesta más eficaz ( con diferencia ). No soy realmente un experto en rendimiento, pero esto realmente se suma si está trabajando con archivos grandes.
Chip
3

Puede resultarle útil. Aquí está el código que usa un clip y una imagen presente en una URL remota.

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

En modelo

class Model < ActiveRecord::Base
  has_attached_file :photo, :styles => { :small => "150x150>", :thumb => "75x75>" }
end
prabu
fuente
3

Como son respuestas antiguas, aquí hay una más nueva:

Agregue la URL remota de imagen a su controlador deseado en la base de datos

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

Edita tu modelo

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

* En Rails4 debes agregar attr_accessible en el controlador.

Actualice su formulario, si permite que otros carguen una imagen desde una URL

<%= f.input :image_remote_url, label: "Enter a URL" %>
Mini John
fuente
¿cuál es la superde?
Terence Chow
La función superse usa para invocar el método original, la búsqueda del cuerpo del método comienza en la superclase del objeto que se encontró que contenía el método original
Mini John
2

Este es un método duro:

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)

donde Uuid.uuid solo crea una identificación aleatoria.

Martin Streicher
fuente
2

En la documentación oficial se informa aquí https://github.com/thoughtbot/paperclip/wiki/Attachment-downloaded-from-a-URL

De todos modos parece no actualizado, porque en la última versión del clip algo ha cambiado y esta línea de código ya no es válida:

user.picture = URI.parse(url)

Genera un error, en particular se genera este error:

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

La nueva sintaxis correcta es esta:

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

También necesitamos agregar estas líneas en el archivo config / initializers / paperclip.rb :

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

Probé esto con la versión de clip 5.3.0y funciona.

Diego D
fuente
Gracias por esto - las cosas de configuración lo arreglaron para mí (Paperclip v6.1.0)
Owlvark