Advertisement
  1. Code
  2. Ruby on Rails

Hochladen von Dateien mit Rails und Dragonfly

by
Read Time:14 minsLanguages:

German (Deutsch) translation by Tatsiana Bochkareva (you can also view the original English article)

Vor einiger Zeit habe ich einen Artikel zum Hochladen von Dateien mit Rails und Shrine geschrieben, in dem erklärt wurde, wie Sie mithilfe des Shrine-Juwels eine Funktion zum Hochladen von Dateien in Ihre Rails-Anwendung einführen. Es gibt jedoch eine Reihe ähnlicher Lösungen, und einer meiner Favoriten ist Dragonfly – eine benutzerfreundliche Upload-Lösung für Rails und Rack von Mark Evans.

Wir haben diese Bibliothek Anfang letzten Jahres behandelt, aber wie bei der meisten Software hilft es, von Zeit zu Zeit einen Blick auf die Bibliotheken zu werfen, um zu sehen, was sich geändert hat und wie wir sie in unserer Anwendung einsetzen können.

In diesem Artikel werde ich Sie durch die Einrichtung von Dragonfly führen und erklären, wie Sie die wichtigsten Funktionen nutzen. Du wirst lernen wie:

  • Integrieren Sie Dragonfly in Ihre Anwendung
  • Konfigurieren Sie Modelle für die Arbeit mit Dragonfly
  • Einführung eines grundlegenden Upload-Mechanismus
  • Validierungen einführen
  • Bildminiaturen erstellen
  • Dateiverarbeitung durchführen
  • Metadaten für hochgeladene Dateien speichern
  • Bereiten Sie eine Anwendung für die Bereitstellung vor

Um die Sache interessanter zu machen, werden wir eine kleine musikalische Anwendung erstellen. Es werden Alben und zugehörige Songs präsentiert, die auf der Website verwaltet und abgespielt werden können.

Der Quellcode für diesen Artikel ist auf GitHub verfügbar. Sie können sich auch die funktionierende Demo der Anwendung ansehen.

Auflisten und Verwalten von Alben

Erstellen Sie zunächst eine neue Rails-Anwendung ohne die Standardtestsuite:

Für diesen Artikel werde ich Rails 5 verwenden, aber die meisten der beschriebenen Konzepte gelten auch für ältere Versionen.

Modell, Controller und Routen erstellen Route

Unsere kleine Musikseite wird zwei Modelle enthalten: Album und Song. Lassen Sie uns zunächst das erste mit den folgenden Feldern erstellen:

  • title (string) – enthält den Titel des Albums
  • singer (string) – Interpret des Albums
  • image_uid (string) – ein spezielles Feld zum Speichern des Vorschaubilds des Albums. Dieses Feld kann beliebig benannt werden, es muss jedoch das Suffix _uid enthalten, wie in der Dragonfly-Dokumentation angegeben.

Erstellen Sie die entsprechende Migration und wenden Sie sie an:

Lassen Sie uns nun einen sehr generischen Controller erstellen, um Alben mit allen Standardaktionen zu verwalten:

albums_controller.rb

Fügen Sie zum Schluss die Routen hinzu:

config/routes.rb

Libelle integrieren

Es ist Zeit für Dragonfly, ins Rampenlicht zu treten. Fügen Sie zuerst den Edelstein zur Gemfile hinzu:

Gemfile

Lauf:

Der letztere Befehl erstellt einen Initialisierer namens dragonfly.rb mit der Standardkonfiguration. Wir werden es vorerst beiseite legen, aber Sie können sich auf der offiziellen Website von Dragonfly über verschiedene Optionen informieren.

Als nächstes müssen Sie unser Modell mit den Methoden von Dragonfly ausstatten. Dies geschieht mit dem dragonfly_accessor:

model/album.rb

Beachten Sie, dass ich hier :image sage – es bezieht sich direkt auf die Spalte image_uid, die wir im vorherigen Abschnitt erstellt haben. Wenn Sie beispielsweise Ihre Spalte photo_uid benannt haben, muss die Methode dragonfly_accessor :photo als Argument erhalten.

Wenn Sie Rails 4 oder 5 verwenden, ist ein weiterer wichtiger Schritt, das :image-Feld (nicht :image_uid!) im Controller als erlaubt zu markieren:

albums_controller.rb

Das ist so ziemlich alles – wir sind bereit, Ansichten zu erstellen und unsere Dateien hochzuladen!

Ansichten erstellen

Beginnen Sie mit der Indexansicht:

views/albums/index.html.erb

Nun der Teil:

views/albums/_album.html.erb

Hier sind zwei Dragonfly-Methoden zu beachten:

  • album.image.url gibt den Pfad zum Bild zurück.
  • album.image_stored? gibt an, ob der Datensatz eine hochgeladene Datei enthält.

Fügen Sie nun die neuen und bearbeitenden Seiten hinzu:

views/albums/new.html.erb

views/albums/edit.html.erb

views/albums/_form.html.erb

Das Formular ist nichts Besonderes, aber beachten Sie noch einmal, dass wir beim Rendern der Dateieingabe :image und nicht :image_uid sagen.

Jetzt können Sie den Server booten und die Upload-Funktion testen!

Bilder entfernen

Die Benutzer können also Alben erstellen und bearbeiten, aber es gibt ein Problem: Sie haben keine Möglichkeit, ein Bild zu entfernen, sondern es durch ein anderes zu ersetzen. Glücklicherweise lässt sich dies sehr einfach beheben, indem Sie ein Kontrollkästchen "Bild entfernen" einführen:

views/albums/_form.html.erb

Wenn dem Album ein Bild zugeordnet ist, zeigen wir es an und rendern ein Kontrollkästchen. Wenn dieses Kontrollkästchen aktiviert ist, wird das Bild entfernt. Beachten Sie, dass, wenn Ihr Feld photo_uid heißt, die entsprechende Methode zum Entfernen des Anhangs remove_photo ist. Einfach, nicht wahr?

Sie müssen lediglich das Attribut remove_image in Ihrem Controller zulassen:

albums_controller.rb

Validierungen hinzufügen

Zu diesem Zeitpunkt funktioniert alles gut, aber wir überprüfen die Eingaben des Benutzers überhaupt nicht, was nicht besonders gut ist. Fügen wir daher Validierungen für das Album-Modell hinzu:

model/album.rb

validates_property ist die Dragonfly-Methode, die verschiedene Aspekte Ihres Anhangs überprüfen kann: Sie können die Erweiterung, den MIME-Typ, die Größe usw. einer Datei überprüfen.

Lassen Sie uns nun ein generisches Partial erstellen, um die gefundenen Fehler zu rendern:

views/shared/_errors.html.erb

Verwenden Sie diesen Teil im Formular:

views/albums/_form.html.erb

Gestalten Sie die Felder mit Fehlern ein wenig, um sie visuell darzustellen:

stylesheets/application.scss

Beibehalten eines Bildes zwischen Anfragen

Nachdem wir Validierungen eingeführt haben, stoßen wir auf ein weiteres Problem (ein ziemlich typisches Szenario, nicht wahr?): Wenn der Benutzer beim Ausfüllen des Formulars Fehler gemacht hat, muss er die Datei erneut auswählen, nachdem er auf die Schaltfläche Senden geklickt hat.

Dragonfly kann Ihnen auch bei der Lösung dieses Problems helfen, indem Sie ein ausgeblendetes Feld retained_* verwenden:

views/albums/_form.html.erb

Vergessen Sie nicht, auch dieses Feld zuzulassen:

albums_controller.rb

Jetzt wird das Bild zwischen den Anfragen beibehalten! Das einzige kleine Problem ist jedoch, dass bei der Datei-Upload-Eingabe immer noch die Meldung "Datei auswählen" angezeigt wird, dies kann jedoch mit etwas Styling und einem Schuss JavaScript behoben werden.

Bilder verarbeiten

Erstellen von Miniaturansichten

Die von unseren Nutzern hochgeladenen Bilder können sehr unterschiedliche Abmessungen haben, was (und wahrscheinlich) negative Auswirkungen auf das Design der Website haben kann (und wird). Wahrscheinlich möchten Sie Bilder auf einige feste Abmessungen verkleinern, und dies ist natürlich möglich, indem Sie die width und height verwenden. Dies ist jedoch kein optimaler Ansatz: Der Browser muss weiterhin Bilder in voller Größe herunterladen und dann verkleinern.

Eine andere Option (die normalerweise viel besser ist) besteht darin, Miniaturansichten von Bildern mit einigen vordefinierten Abmessungen auf dem Server zu generieren. Mit Dragonfly geht das ganz einfach:

views/albums/_album.html.erb

250x250 sind natürlich die Abmessungen, während # die Geometrie ist, die "Größe ändern und bei Bedarf zuschneiden" bedeutet, um das Seitenverhältnis mit Schwerpunkt beizubehalten. Informationen zu anderen Geometrien finden Sie auf der Website von Dragonfly.

Die thumb-Methode wird von ImageMagick unterstützt – eine großartige Lösung zum Erstellen und Bearbeiten von Bildern. Um die funktionierende Demo lokal zu sehen, müssen Sie daher ImageMagick installieren (alle wichtigen Plattformen werden unterstützt).

Die Unterstützung für ImageMagick ist standardmäßig im Initialisierer von Dragonfly aktiviert:

config/initializers/dragonfly.rb

Jetzt werden Miniaturansichten generiert, aber nirgendwo gespeichert. Dies bedeutet, dass jedes Mal, wenn ein Benutzer die Albenseite besucht, Miniaturansichten neu generiert werden. Es gibt zwei Möglichkeiten, dieses Problem zu umgehen: durch Generieren nach dem Speichern des Datensatzes oder durch Ausführen der Generierung im laufenden Betrieb.

Die erste Option besteht darin, eine neue Spalte zum Speichern des Thumbnails einzuführen und die Methode dragonfly_accessor zu optimieren. Erstellen und wenden Sie eine neue Migration an:

Ändern Sie nun das Modell:

model/album.rb

Beachten Sie, dass jetzt der erste Aufruf von dragonfly_accessor einen Block sendet, der tatsächlich das Thumbnail für uns generiert und in das image_thumb kopiert. Verwenden Sie jetzt einfach die image_thumb-Methode in Ihren Ansichten:

views/albums/_album.html.erb

Diese Lösung ist die einfachste, wird jedoch von den offiziellen Dokumenten nicht empfohlen und, was noch schlimmer ist, zum Zeitpunkt des Schreibens funktioniert sie nicht mit den retained_*-Feldern.

Lassen Sie mich Ihnen daher eine weitere Option zeigen: Miniaturansichten im Handumdrehen erstellen. Dazu müssen Sie ein neues Modell erstellen und die Konfigurationsdatei von Dragonfly optimieren. Zuerst das Modell:

Die thumbs-Tabelle hostet Ihre Thumbnails, aber sie werden bei Bedarf generiert. Um dies zu erreichen, müssen wir die url-Methode im Dragonfly-Initialisierer neu definieren:

config/initializers/dragonfly.rb

Fügen Sie nun ein neues Album hinzu und besuchen Sie die Stammseite. Wenn Sie dies zum ersten Mal tun, wird die folgende Ausgabe in die Protokolle gedruckt:

Dies bedeutet effektiv, dass das Thumbnail von ImageMagick für uns generiert wird. Wenn Sie die Seite jedoch neu laden, wird diese Zeile nicht mehr angezeigt, was bedeutet, dass das Thumbnail zwischengespeichert wurde! Sie können mehr über diese Funktion auf der Website von Dragonfly lesen.

Mehr Verarbeitung

Sie können praktisch jede Manipulation an Ihren Bildern vornehmen, nachdem sie hochgeladen wurden. Dies kann innerhalb des after_assign-Callbacks erfolgen. Lassen Sie uns zum Beispiel alle unsere Bilder mit 90% Qualität in das JPEG-Format konvertieren:

Es gibt viele weitere Aktionen, die Sie ausführen können: Bilder drehen und zuschneiden, mit einem anderen Format codieren, Text darauf schreiben, mit anderen Bildern mischen (z. B. um ein Wasserzeichen zu platzieren) usw. Weitere Beispiele finden Sie im Abschnitt ImageMagick auf der Dragonfly-Website.

Hochladen und Verwalten von Songs

Der Hauptteil unserer Musikseite sind natürlich Lieder, also fügen wir sie jetzt hinzu. Jeder Song hat einen Titel und eine Musikdatei und gehört zu einem Album:

Schließen Sie die Dragonfly-Methoden an, wie wir es für das Album-Modell getan haben:

models/song.rb

Vergessen Sie nicht, eine has_many-Beziehung einzurichten:

models/album.rb

Fügen Sie neue Routen hinzu. Ein Song existiert immer im Rahmen eines Albums, daher werde ich diese Routen verschachteln:

config/routes.rb

Erstellen Sie einen ganz einfachen Controller (auch hier vergessen Sie nicht, das track zuzulassen):

songs_controller.rb

Zeigen Sie die Songs und einen Link an, um einen neuen hinzuzufügen:

views/albums/show.html.erb

Codieren Sie das Formular:

views/songs/new.html.erb

Schließlich fügen Sie den _song-Teil hinzu:

views/songs/_song.html.erb

Hier verwende ich das HTML5-audio-Tag, das für ältere Browser nicht funktioniert. Wenn Sie also solche Browser unterstützen möchten, verwenden Sie ein Polyfill.

Wie Sie sehen, ist der gesamte Prozess sehr einfach. Dragonfly ist es egal, welche Art von Datei Sie hochladen möchten; Alles, was Sie tun müssen, ist eine dragonfly_accessor-Methode bereitzustellen, ein geeignetes Feld hinzuzufügen, es zuzulassen und ein Datei-Input-Tag zu rendern.

Speichern von Metadaten

Wenn ich eine Playlist öffne, erwarte ich zusätzliche Informationen zu jedem Song, z. B. seine Dauer oder Bitrate. Natürlich werden diese Informationen standardmäßig nirgendwo gespeichert, aber wir können das ganz einfach beheben. Dragonfly ermöglicht es uns, zusätzliche Daten zu jeder hochgeladenen Datei bereitzustellen und diese später mithilfe der meta-Methode abzurufen.

Etwas komplexer ist es jedoch, wenn wir mit Audio oder Video arbeiten, denn um deren Metadaten abzurufen, wird ein spezielles Gem streamio-ffmpeg benötigt. Dieses Juwel wiederum basiert auf FFmpeg. Um fortzufahren, müssen Sie es auf Ihrem PC installieren.

Fügen Sie streamio-ffmpeg in das Gemfile hinzu:

Gemfile

Es installieren:

Jetzt können wir denselben after_assign-Callback verwenden, den wir bereits in den vorherigen Abschnitten gesehen haben:

models/song.rb

Beachten Sie, dass ich hier eine path-Methode und keine url verwende, da wir zu diesem Zeitpunkt mit einer tempfile arbeiten. Als nächstes extrahieren wir einfach die Dauer des Songs (in Minuten und Sekunden mit führenden Nullen umwandeln) und seine Bitrate (umwandeln in Kilobytes pro Sekunde).

Zuletzt Metadaten in der Ansicht anzeigen:

views/songs/_song.html.erb

Wenn Sie den Inhalt des Ordners public/system/dragonfly (der Standardspeicherort zum Hosten der Uploads) überprüfen, werden Sie einige .yml-Dateien bemerken – sie speichern alle Metainformationen im YAML-Format.

Bereitstellung auf Heroku

Das letzte Thema, das wir heute behandeln, ist die Vorbereitung Ihrer Anwendung vor der Bereitstellung auf der Heroku-Cloud-Plattform. Das Hauptproblem ist, dass Heroku Ihnen nicht erlaubt, benutzerdefinierte Dateien (wie Uploads) zu speichern, sodass wir uns auf einen Cloud-Speicherdienst wie Amazon S3 verlassen müssen. Zum Glück lässt sich Dragonfly problemlos damit integrieren.

Sie müssen lediglich ein neues Konto bei AWS registrieren (falls Sie es noch nicht haben), einen Benutzer mit Zugriffsberechtigung für S3-Buckets erstellen und das Schlüsselpaar des Benutzers an einem sicheren Ort aufschreiben. Sie können ein Root-Schlüsselpaar verwenden, dies wird jedoch wirklich nicht empfohlen. Erstellen Sie zuletzt einen S3-Bucket.

Kehren Sie zu unserer Rails-Anwendung zurück und geben Sie ein neues Juwel ein:

Gemfile

Es installieren:

Passen Sie dann die Konfiguration von Dragonfly an, um S3 in einer Produktionsumgebung zu verwenden:

config/initializers/dragonfly.rb

Um ENV-Variablen auf Heroku bereitzustellen, verwenden Sie diesen Befehl:

Wenn Sie die Integration mit S3 lokal testen möchten, können Sie ein Gem wie dotenv-rails verwenden, um Umgebungsvariablen zu verwalten. Denken Sie jedoch daran, dass Ihr AWS-Schlüsselpaar nicht öffentlich zugänglich gemacht werden darf!

Ein weiteres kleines Problem, auf das ich beim Bereitstellen von Heroku gestoßen bin, war das Fehlen von FFmpeg. Die Sache ist die, dass wenn eine neue Heroku-Anwendung erstellt wird, diese über eine Reihe von Diensten verfügt, die häufig verwendet werden (beispielsweise ist ImageMagick standardmäßig verfügbar). Andere Dienste können als Heroku-Addons oder in Form von Buildpacks installiert werden. Führen Sie den folgenden Befehl aus, um ein FFmpeg-Buildpack hinzuzufügen:

Jetzt ist alles fertig und Sie können Ihre Musikanwendung mit der Welt teilen!

Abschluss

Das war eine lange Reise, nicht wahr? Heute haben wir Dragonfly besprochen – eine Lösung zum Hochladen von Dateien in Rails. Wir haben die grundlegende Einrichtung, einige Konfigurationsoptionen, die Erstellung von Miniaturansichten, die Verarbeitung und das Speichern von Metadaten gesehen. Außerdem haben wir Dragonfly in den Amazon S3-Service integriert und unsere Anwendung für die Bereitstellung in der Produktion vorbereitet.

Natürlich haben wir in diesem Artikel nicht alle Aspekte von Dragonfly besprochen, also stöbern Sie auf der offiziellen Website nach ausführlicher Dokumentation und nützlichen Beispielen. Wenn Sie weitere Fragen haben oder bei einigen Codebeispielen nicht weiterkommen, zögern Sie nicht, mich zu kontaktieren.

Vielen Dank, dass Sie bei mir bleiben, und bis bald!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.