Come posso scaricare un file da un URL e salvarlo in Rails?


197

Ho un URL per un'immagine che voglio salvare localmente, in modo da poter usare Paperclip per produrre una miniatura per la mia applicazione. Qual è il modo migliore per scaricare e salvare l'immagine? (Ho esaminato la gestione dei file ruby ​​ma non ho riscontrato nulla.)

Risposte:


315

Prova questo:

require 'open-uri'
open('image.png', 'wb') do |file|
  file << open('http://example.com/image.png').read
end

1
Questo funziona Grazie. Ho provato questo su un'immagine. L'immagine non è stata scritta correttamente nel file. Come se fosse stato corrotto o qualcosa del genere. Potresti anche guidarmi a fare lo stesso in un'applicazione Rails. Posso usarlo in un'applicazione Rails?
Alok Swain,

Sì, puoi usarlo in un'applicazione rotaie. Il file non scritto correttamente è probabilmente perché ho dimenticato di aprire la destinazione in modalità di scrittura binaria. Lo modificherò ora.
Levi,

78
Questo legge l'intero file in memoria. Il modo migliore èIO.copy_stream(open('http://example.com/image.png'), 'destination.png')
janko-m

3
rails 5, 2016, non avevo bisogno, ho require 'open-uri'usato solo il codice sotto di esso
Mirror318

1
questa risposta non ha funzionato per me. la risposta corretta è qui: stackoverflow.com/a/29743394/1536309
Blair Anderson

147

Una versione ancora più breve:

require 'open-uri'
download = open('http://example.com/image.png')
IO.copy_stream(download, '~/image.png')

Per mantenere lo stesso nome file:

IO.copy_stream(download, "~/#{download.base_uri.to_s.split('/')[-1]}")

2
E più efficiente poiché l'output non è archiviato come stringa in memoria. +1
Itay Grudev,

2
Anche se in realtà è utile avere entrambe le risposte visualizzate, quindi le persone come me possono vederle entrambe, pensare alle differenze e quindi scegliere questa risposta consapevolmente per le giuste ragioni :)
Maxwell Evans

30

Se stai usando PaperClip, il download da un URL ora viene gestito automaticamente.

Supponendo che tu abbia qualcosa del tipo:

class MyModel < ActiveRecord::Base
  has_attached_file :image, ...
end

Sul tuo modello, specifica semplicemente l'immagine come un URL, qualcosa del genere (scritto in deliberatamente longhand):

@my_model = MyModel.new
image_url = params[:image_url]
@my_model.image = URI.parse(image_url)

Probabilmente vorrai metterlo in un metodo nel tuo modello. Funzionerà bene anche sul filesystem temporaneo di Heroku.

Paperclip lo prenderà da lì.

fonte: documentazione graffetta


4
Per i futuri ricercatori, Paperclip non lo consente più per impostazione predefinita: medium.com/in-the-weeds/…
Alex Dunae

14

Penso che questo sia il modo più chiaro:

require 'open-uri'

File.write 'image.png', open('http://example.com/image.png').read

saggio sono nuovo su rotaie, dove posso aggiungere questo codice nel modello o controller o in vista
adarsh

1
Dipende, ma in genere dovresti fare qualcosa del genere all'interno di un modello o di un metodo controller. In un contesto Rails, probabilmente stai meglio usando gli strumenti del framework come ActiveStorage, piuttosto che scrivere direttamente su disco.
Sage Ross,

10

Dai un'occhiata a Net :: HTTP nella libreria standard. La documentazione fornisce numerosi esempi su come scaricare documenti tramite HTTP.


2
Questa risposta richiede maggiore visibilità poiché Kernel#openconsente non solo l'accesso ai file, ma anche l'elaborazione dell'invocazione con il prefisso di un simbolo di pipe (ad es open("| ls").). Pertanto, può comportare un grave rischio per la sicurezza utilizzando input variabili all'argomento di Kernel#open.
ConorB,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.