Enregistrer l'image de l'URL par un trombone

Réponses:

154

Voici un moyen simple:

require "open-uri"

class User < ActiveRecord::Base
  has_attached_file :picture

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

Puis simplement:

user.picture_from_url "http://www.google.com/images/logos/ps_logo2.png"
Nicolas Blanco
la source
7
Si vous devez utiliser update_attributesrenommer picture_from_urlen picture_url=(value)par exemple.
Daniel Rikowski
3
Ceci est potentiellement non sécurisé car un utilisateur pourrait appeler user.picture_from_url('/etc/password'). C'est probablement bien dans la plupart des situations.
David Tuite
1
Pour des raisons de sécurité, vous devriez mettre sur liste blanche le schéma de l'URI et les hôtes privés sur liste noire
John Douthat
3
Voir la réponse ci-dessous pour une solution encore meilleure.
geekazoid
6
En utilisant open(url), le nom de fichier n'est pas précis, par exemple open-uri20150106-10034-lpd5fm.au lieu de ef3a601e_ef3d008b_ef3d0f7e.jpg.
Joshua Pinter
196

Dans Paperclip 3.1.4, c'est devenu encore plus simple.

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

C'est légèrement mieux que open (url). Parce qu'avec open (url), vous obtiendrez "stringio.txt" comme nom de fichier. Avec ce qui précède, vous obtiendrez un nom correct du fichier en fonction de l'URL. c'est à dire

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

self.picture_file_name    # => "avatar.png"
self.picture_content_type # => "image/png"
Aditya Sanghi
la source
3
Depuis le wiki paperclip : github.com/thoughtbot/paperclip/wiki/ ... Je l'ai exécuté avec succès dans la console, l'application est dans heroku.
Donny Kurnia
3
Pour votre information, pour urls S3 je reçois toujours application/octet_streamcomme content_type.
Joshua Pinter
5
Si vous utilisez toujours un trombone après sa dépréciation, vous devrez peut-être également vous assurer que le chargeur URI IO est chargé: Paperclip :: UriAdapter.register (dans la configuration, ou temporairement via la console si c'est tout ce dont vous avez besoin)
Msencenb
L'approche est correcte mais dans la dernière version le sintax est changé! Découvrez ma réponse ci-dessous => stackoverflow.com/a/56039191/3182171
Diego D
Vous devez ajouter une entrée dans l'initialiseur github.com/thoughtbot/paperclip/wiki/…
ianpetzer
16

Cela n'a pas fonctionné pour moi jusqu'à ce que j'utilise "open" pour l'URI analysé. une fois que j'ai ajouté "ouvert", cela a fonctionné!

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

Ma version trombone est la 4.2.1

Avant de l'ouvrir, il ne détectait pas le type de contenu correctement, car ce n'était pas un fichier. Il dirait image_content_type: "binary / octet-stream", et même si je le remplace avec le bon type de contenu, cela ne fonctionnerait pas.

Mïchael Makaröv
la source
Merci pour cela! Exactement ce qui me manquait moi-même.
Dan
Vous perdrez votre exension si vous faites cela. Vous avez besoin de Paperclip :: UriAdapter.register dans l'initialiseur .. alors vous n'avez pas besoin de .open à la fin. Voir github.com/thoughtbot/paperclip/wiki/…
ianpetzer
15

Commencez par télécharger l'image avec la curbgemme dans a TempFile, puis attribuez simplement l'objet tempfile et enregistrez votre modèle.

Ariéjan
la source
2
Je ne vois pas ce qui ne va pas avec cette réponse, voter pour parce que je vois un vote contre.
jpemberthy
C'est la réponse la plus performante ( de loin ). Je ne suis pas vraiment un geek de la performance, mais cela s'ajoute vraiment si vous travaillez avec de gros fichiers.
Puce du
3

Cela peut vous être utile. Voici le code utilisant un trombone et une image présente dans l'URL distante.

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

Dans le modèle

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

Comme ce sont des anciennes réponses, voici une nouvelle:

Ajouter l'URL d'image distante à votre contrôleur souhaité dans la base de données

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

Modifier votre modèle

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

* Dans Rails4, vous devez ajouter l'attr_accessible dans le contrôleur.

Mettez à jour votre formulaire si vous autorisez d'autres personnes à télécharger une image à partir d'une URL

<%= f.input :image_remote_url, label: "Enter a URL" %>
Mini John
la source
à quoi ça sert super?
Terence Chow
La fonction superest utilisée pour invoquer la méthode d'origine, la recherche du corps de la méthode commence dans la super classe de l'objet qui contient la méthode d'origine
Mini John
2

C'est une méthode hardcore:

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)

où Uuid.uuid crée juste un identifiant aléatoire.

Martin Streicher
la source
2

La documentation officielle est rapportée ici https://github.com/thoughtbot/paperclip/wiki/Attachment-downloaded-from-a-URL

Quoi qu'il en soit, il ne semble pas mis à jour, car dans la dernière version de paperclip quelque chose a changé et cette ligne de code n'est plus valide:

user.picture = URI.parse(url)

Cela soulève une erreur, en particulier cette erreur est déclenchée:

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

La nouvelle syntaxe correcte est celle-ci:

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

Nous devons également ajouter ces lignes dans le fichier config / initializers / paperclip.rb :

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

Testé cela avec la version trombone 5.3.0et cela fonctionne.

Diego D
la source
Merci pour cela - les trucs de configuration l'ont corrigé pour moi (Paperclip v6.1.0)
Owlvark