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.)

Antworten:


315

Versuche dies:

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

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]}")

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


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 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.


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.