Wie kann ich eine Datei von einer URL herunterladen und in Rails speichern?

197

Ich habe eine URL zu einem Bild, das ich lokal speichern möchte, damit ich mit Paperclip ein Miniaturbild für meine Anwendung erstellen kann. Wie kann ich das Bild am besten herunterladen und speichern? (Ich habe mich mit der Handhabung von Ruby-Dateien befasst, bin aber auf nichts gestoßen.)

Alok Swain
quelle

Antworten:

315

Versuche dies:

require 'open-uri'
open('image.png', 'wb') do |file|
  file << open('http://example.com/image.png').read
end
Levi
quelle
1
Das funktioniert. Vielen Dank. Ich habe das an einem Bild versucht. Das Bild wurde nicht richtig in die Datei geschrieben. Als ob es beschädigt worden wäre oder so. Könnten Sie mich auch anleiten, dies auch in einer Rails-Anwendung zu tun? Kann ich dies in einer Rails-Anwendung verwenden?
Alok Swain
Ja, Sie können es in einer Schienenanwendung verwenden. Die Datei, die nicht richtig geschrieben wird, liegt wahrscheinlich daran, dass ich vergessen habe, das Ziel im binären Schreibmodus zu öffnen. Ich werde das jetzt bearbeiten.
Levi
77
Dies liest die gesamte Datei im Speicher. Der beste Weg istIO.copy_stream(open('http://example.com/image.png'), 'destination.png')
Janko-m
3
Schienen 5, 2016, ich brauchte nicht require 'open-uri', nur den Code darunter verwendet
Mirror318
1
Diese Antwort hat bei mir nicht funktioniert. Die richtige Antwort finden Sie hier: stackoverflow.com/a/29743394/1536309
Blair Anderson
147

Eine noch kürzere Version:

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

So behalten Sie den gleichen Dateinamen bei:

IO.copy_stream(download, "~/#{download.base_uri.to_s.split('/')[-1]}")
Clemens Helm
quelle
2
Und effizienter, da die Ausgabe nicht als Zeichenfolge im Speicher gespeichert wird. +1
Itay Grudev
2
Obwohl es tatsächlich nützlich ist, beide Antworten anzuzeigen, können Leute wie ich beide sehen, über die Unterschiede nachdenken und diese Antwort dann aus den richtigen Gründen bewusst auswählen :)
Maxwell Evans
29

Wenn Sie PaperClip verwenden, wird das Herunterladen von einer URL jetzt automatisch durchgeführt.

Angenommen, Sie haben so etwas wie:

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

Geben Sie in Ihrem Modell einfach das Bild als URL an, etwa wie folgt (absichtlich absichtlich geschrieben):

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

Sie möchten dies wahrscheinlich in eine Methode in Ihrem Modell einfügen. Dies funktioniert auch auf dem temporären Dateisystem von Heroku einwandfrei.

Büroklammer wird es von dort nehmen.

Quelle: Büroklammerdokumentation

überleuchtet
quelle
4
Für zukünftige Suchende erlaubt Paperclip dies nicht mehr standardmäßig: medium.com/in-the-weeds/…
Alex Dunae
14

Ich denke, das ist der klarste Weg:

require 'open-uri'

File.write 'image.png', open('http://example.com/image.png').read
Salbei Ross
quelle
Salbei Ich bin neu in Rails, wo ich diesen Code in Modell oder Controller oder in Ansicht hinzufügen kann
Adarsh
1
Es hängt davon ab, aber normalerweise würden Sie so etwas in einem Modell oder einer Controller-Methode tun. In einem Rails-Kontext ist es wahrscheinlich besser, die Tools des Frameworks wie ActiveStorage zu verwenden, als direkt auf die Festplatte zu schreiben.
Sage Ross
10

Überprüfen Sie Net :: HTTP in der Standardbibliothek. Die Dokumentation enthält mehrere Beispiele zum Herunterladen von Dokumenten über HTTP.

Pär Wieslander
quelle
2
Diese Antwort muss sichtbarer sein, da sie Kernel#opennicht nur den Dateizugriff ermöglicht, sondern auch den Aufruf durch Präfixieren eines Pipe-Symbols (z open("| ls"). B. ) verarbeitet. Daher kann es zu einem ernsthaften Sicherheitsrisiko kommen, wenn variable Eingaben für das Argument von verwendet werden Kernel#open.
ConorB