Salvar imagem do URL por clipe de papel

Respostas:

154

Aqui está uma maneira simples:

require "open-uri"

class User < ActiveRecord::Base
  has_attached_file :picture

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

Então simplesmente:

user.picture_from_url "http://www.google.com/images/logos/ps_logo2.png"
Nicolas Blanco
fonte
7
Se você precisar usar update_attributesrenomear picture_from_urlpara, picture_url=(value)por exemplo.
precisa
3
Isso é potencialmente inseguro porque um usuário pode ligar user.picture_from_url('/etc/password'). Provavelmente é bom na maioria das situações.
David Tuite
1
Por segurança, você deve whitelist esquema da URI e exércitos privados lista negra
John Douthat
3
Veja a resposta abaixo para uma solução ainda melhor.
precisa saber é o seguinte
6
Usando open(url), o nome do arquivo não é exato, por exemplo, em open-uri20150106-10034-lpd5fm.vez de ef3a601e_ef3d008b_ef3d0f7e.jpg.
Joshua Pinter
196

No Paperclip 3.1.4, ficou ainda mais simples.

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

Isso é um pouco melhor que aberto (url). Porque com open (url) você receberá "stringio.txt" como o nome do arquivo. Com o exposto acima, você receberá um nome adequado do arquivo com base na URL. ie

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

self.picture_file_name    # => "avatar.png"
self.picture_content_type # => "image/png"
Aditya Sanghi
fonte
3
No wiki do paperclip: github.com/thoughtbot/paperclip/wiki/… Eu o executei com êxito no console, o aplicativo está em heroku.
Donny Kurnia
3
FYI, para URLs S3 eu ainda recebo application/octet_streamcomo content_type.
21415 Joshua Pinter
5
Se você ainda estiver usando o clipe de papel após a sua suspensão, talvez também seja necessário garantir que o carregador do URI IO seja carregado: Paperclip :: UriAdapter.register (na configuração ou temporariamente através do console, se isso é tudo o que você precisa)
Msencenb
A abordagem está correta, mas na última versão a sintaxe foi alterada! Veja a minha resposta abaixo => stackoverflow.com/a/56039191/3182171 #
D Diego D
Você precisa adicionar entrada no initializer github.com/thoughtbot/paperclip/wiki/...
ianpetzer
16

Não funcionou para mim até que eu usei "aberto" para URI analisado. uma vez que adicionei "aberto", funcionou!

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

Minha versão do clipe de papel é 4.2.1

Antes da abertura, ele não detectava o tipo de conteúdo certo, porque não era um arquivo. Diria image_content_type: "binary / octet-stream" e, mesmo que eu o substitua pelo tipo de conteúdo correto, não funcionará.

Mïchael Makaröv
fonte
Obrigado por isso! Exatamente o que eu estava sentindo falta de mim mesma.
Dan
Você perderá sua tensão se fizer isso. Você precisa do Paperclip :: UriAdapter.register no inicializador. Depois, não precisa .open no final. Veja github.com/thoughtbot/paperclip/wiki/…
ianpetzer
15

Primeiro faça o download da imagem com a curbgema para a TempFilee, em seguida, simplesmente atribua o objeto tempfile e salve seu modelo.

Ariejan
fonte
2
Não vejo o que há de errado com esta resposta, votando porque estou vendo uma votação negativa.
precisa saber é o seguinte
Esta é a resposta de melhor desempenho ( de longe ). Eu não sou realmente um nerd de desempenho, mas isso realmente se soma se você estiver trabalhando com arquivos grandes.
Chip
3

Pode ser útil para você. Aqui está o código usando um clipe de papel e uma imagem presente no URL remoto.

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

No modelo

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

Como esses são antigos respondedores, aqui está um mais novo:

Adicione o URL remoto da imagem ao controlador desejado no banco de dados

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

Edite seu 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

* No Rails4, você precisa adicionar o attr_accessible no Controller.

Atualize seu formulário, se você permitir que outro faça upload de uma imagem de um URL

<%= f.input :image_remote_url, label: "Enter a URL" %>
Mini John
fonte
para que serve super?
Terence Chow
A função superé usada para invocar o método original, em busca do corpo do método começa na classe super do objeto que foi encontrado para conter o método original
Mini John
2

Este é um método incondicional:

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)

onde Uuid.uuid apenas cria algum ID aleatório.

Martin Streicher
fonte
2

Na documentação oficial é relatada aqui https://github.com/thoughtbot/paperclip/wiki/Attachment-downloaded-from-a-URL

De qualquer forma, não parece atualizado, porque na última versão do clipe de papel algo mudou e esta linha de código não é mais válida:

user.picture = URI.parse(url)

Ele gera um erro, em particular esse erro é gerado:

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

A nova sintaxe correta é esta:

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

Também precisamos adicionar essas linhas no arquivo config / initializers / paperclip.rb :

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

Testei isso com a versão de clipe de papel 5.3.0e funciona.

Diego D
fonte
Obrigado por este - o material de configuração fixa para mim (Paperclip V6.1.0)
Owlvark