Zapisz obraz z adresu URL za pomocą spinacza

Odpowiedzi:

154

Oto prosty sposób:

require "open-uri"

class User < ActiveRecord::Base
  has_attached_file :picture

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

Następnie po prostu:

user.picture_from_url "http://www.google.com/images/logos/ps_logo2.png"
Nicolas Blanco
źródło
7
Jeśli trzeba użyć update_attributesZmień nazwę picture_from_url, aby picture_url=(value)na przykład.
Daniel Rikowski
3
Jest to potencjalnie niebezpieczne, ponieważ użytkownik może zadzwonić user.picture_from_url('/etc/password'). Jednak prawdopodobnie jest w porządku w większości sytuacji.
David Tuite,
1
Ze względów bezpieczeństwa powinieneś umieścić na białej liście schemat identyfikatora URI i czarną listę prywatnych hostów
John Douthat,
3
Zobacz odpowiedź poniżej, aby uzyskać jeszcze lepsze rozwiązanie.
geekazoid
6
Używając open(url), nazwa pliku nie jest dokładna, np. open-uri20150106-10034-lpd5fm.Zamiast ef3a601e_ef3d008b_ef3d0f7e.jpg.
Joshua Pinter
196

W Paperclip 3.1.4 stało się to jeszcze prostsze.

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

Jest to nieco lepsze niż open (url). Ponieważ w przypadku open (url) jako nazwę pliku otrzymasz „stringio.txt”. Z powyższym otrzymasz właściwą nazwę pliku na podstawie adresu URL. to znaczy

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

self.picture_file_name    # => "avatar.png"
self.picture_content_type # => "image/png"
Aditya Sanghi
źródło
3
Z wiki spinacza: github.com/thoughtbot/paperclip/wiki/ ... Udało mi się to uruchomić w konsoli, aplikacja jest w heroku.
Donny Kurnia
3
FYI, dla adresów URL S3 nadal otrzymuję application/octet_streamjako content_type.
Joshua Pinter
5
Jeśli nadal używasz spinacza po jego wycofaniu, może być konieczne załadowanie modułu ładującego IO URI: Paperclip :: UriAdapter.register (w konfiguracji lub tymczasowo przez konsolę, jeśli to wszystko, czego potrzebujesz)
Msencenb
Podejście jest poprawne, ale w ostatniej wersji zmieniono sintax! Sprawdź moją odpowiedź poniżej => stackoverflow.com/a/56039191/3182171
Diego D
Trzeba dodać wpis w initializer github.com/thoughtbot/paperclip/wiki/...
ianpetzer
16

U mnie nie działało, dopóki nie użyłem „open” dla przeanalizowanego identyfikatora URI. po dodaniu „otwórz” zadziałało!

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

Moja wersja spinacza to 4.2.1

Przed otwarciem nie wykryłby prawidłowego typu zawartości, ponieważ nie był to plik. Powiedziałby image_content_type: "binarny / strumień oktetu", a nawet gdybym nadpisał go odpowiednim typem treści, nie zadziała.

Mïchael Makaröv
źródło
Dzięki za to! Dokładnie to, czego mi brakowało.
Dan,
Jeśli to zrobisz, stracisz nadwyżkę. Potrzebujesz Paperclip :: UriAdapter.register w inicjatorze ... wtedy nie potrzebujesz na końcu .open. Zobacz github.com/thoughtbot/paperclip/wiki/…
ianpetzer
15

Najpierw pobierz obraz z curbklejnotem do pliku, TempFilea następnie po prostu przypisz obiekt tymczasowego pliku i zapisz model.

Ariejan
źródło
2
Nie rozumiem, co jest nie tak w tej odpowiedzi, głosowanie za nią, ponieważ widzę głos negatywny.
jpemberthy
To jest najbardziej skuteczna odpowiedź (jak dotąd ). Nie jestem maniakiem wydajności, ale to naprawdę się sumuje, jeśli pracujesz z dużymi plikami.
Chip
3

Może ci się to przydać. Oto kod wykorzystujący spinacz i obraz obecny w zdalnym adresie URL.

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

W modelu

class Model < ActiveRecord::Base
  has_attached_file :photo, :styles => { :small => "150x150>", :thumb => "75x75>" }
end
prabu
źródło
3

Ponieważ to są stare Odpowiedź, oto nowsza:

Dodaj zdalny adres URL obrazu do żądanego kontrolera w bazie danych

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

Edytuj swój model

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

* W Rails4 musisz dodać attr_accessible w kontrolerze.

Zaktualizuj swój formularz, jeśli zezwalasz innym na przesyłanie obrazu z adresu URL

<%= f.input :image_remote_url, label: "Enter a URL" %>
Mini John
źródło
co to jest superza?
Terence Chow
Funkcja supersłuży do wywoływania oryginalnej metody, wyszukiwanie treści metody rozpoczyna się w superklasie obiektu, w którym znaleziono oryginalną metodę
Mini John.
2

To jest metoda 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)

gdzie Uuid.uuid po prostu tworzy losowy identyfikator.

Martin Streicher
źródło
2

Do oficjalnej dokumentacji zgłoszono tutaj https://github.com/thoughtbot/paperclip/wiki/Attachment-downloaded-from-a-URL

W każdym razie wygląda na to, że nie został zaktualizowany, ponieważ w ostatniej wersji spinacza coś się zmieniło i ta linia kodu nie jest już poprawna:

user.picture = URI.parse(url)

Podnosi błąd, w szczególności ten błąd jest podnoszony:

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

Nowa poprawna składnia to:

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

Musimy również dodać te linie do pliku config / initializers / paperclip.rb :

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

Przetestowałem to z wersją spinacza 5.3.0i działa.

Diego D.
źródło
Dzięki za to - konfiguracja naprawiła to za mnie (Paperclip v6.1.0)
Owlvark