Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Ruby on Rails

Hochladen von Dateien mit Schienen und Schrein

by
Difficulty:IntermediateLength:LongLanguages:

German (Deutsch) translation by Alex Grigorovich (you can also view the original English article)

Es gibt viele Edelsteine zum Hochladen von Dateien wie CarrierWave, Paperclip und Dragonfly, um nur einige zu nennen. Sie haben alle ihre Besonderheiten, und wahrscheinlich haben Sie bereits mindestens einen dieser Edelsteine verwendet.

Heute möchte ich jedoch eine relativ neue, aber sehr coole Lösung namens Shrine vorstellen, die von Janko Marohnić entwickelt wurde. Im Gegensatz zu einigen anderen ähnlichen Juwelen hat es einen modularen Ansatz, was bedeutet, dass jedes Feature als Modul (oder Plugin in Shrines Terminologie) gepackt ist. Möchten Sie Validierungen unterstützen? Fügen Sie ein Plugin hinzu. Möchten Sie eine Dateiverarbeitung durchführen? Füge ein Plugin hinzu! Ich mag diesen Ansatz sehr, da Sie so einfach steuern können, welche Funktionen für welches Modell verfügbar sind.

In diesem Artikel werde ich Ihnen zeigen, wie Sie:

  • Shrine in eine Rails-Anwendung integrieren
  • konfigurieren Sie es (global und pro Modell)
  • Fügen Sie die Möglichkeit zum Hochladen von Dateien hinzu
  • Dateien verarbeiten
  • Validierungsregeln hinzufügen
  • Speichern Sie zusätzliche Metadaten und verwenden Sie File Cloud Storage mit Amazon S3

Der Quellcode für diesen Artikel ist auf GitHub verfügbar.

Die funktionierende Demo finden Sie hier.

Schrein integrieren

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

Ich werde Rails 5 für diese Demo verwenden, aber die meisten Konzepte gelten auch für die Versionen 3 und 4.

Lass den Schrein gem in deine Gem-Datei fallen:

Dann renne:

Jetzt benötigen wir ein Modell, das ich Photo nennen werde. Shrine speichert alle dateibezogenen Informationen in einer speziellen Textspalte, die mit dem Suffix _data endet. Erstellen Sie die entsprechende Migration und wenden Sie sie an:

Beachten Sie, dass für ältere Versionen von Rails der letztere Befehl lauten sollte:

Konfigurationsoptionen für Shrine können sowohl global als auch pro Modell festgelegt werden. Globale Einstellungen werden natürlich in der Initialisierungsdatei vorgenommen. Dort werde ich die notwendigen Dateien und Plugins anschließen. Plugins werden in Shrine verwendet, um Funktionen in separate Module zu extrahieren, sodass Sie die vollständige Kontrolle über alle verfügbaren Funktionen haben. Beispielsweise gibt es Plugins für die Validierung, Bildverarbeitung, das Zwischenspeichern von Anhängen und mehr.

Fügen wir zunächst zwei Plugins hinzu: eines zur Unterstützung von ActiveRecord und eines zur Einrichtung der Protokollierung. Sie werden global aufgenommen. Richten Sie außerdem den Dateisystemspeicher ein:

config/initializers/shrine.rb

Logger gibt einfach einige Debugging-Informationen in der Konsole aus, damit Sie angeben, wie viel Zeit für die Verarbeitung einer Datei aufgewendet wurde. Dies kann nützlich sein.

Alle hochgeladenen Dateien werden im Verzeichnis public/uploads gespeichert. Ich möchte diese Dateien nicht in Git verfolgen, also schließe diesen Ordner aus:

.gitignore

Erstellen Sie jetzt eine spezielle "uploader"-Klasse, in der modellspezifische Einstellungen gehostet werden. Im Moment wird diese Klasse leer sein:

models/image_uploader.rb

Fügen Sie diese Klasse zuletzt in das Photo-Modell ein:

models/photo.rb

[:image] fügt ein virtuelles Attribut hinzu, das beim Erstellen eines Formulars verwendet wird. Die obige Zeile kann so umgeschrieben werden:

Es ist nett! Jetzt ist das Modell mit der Funktionalität von Shrine ausgestattet, und wir können mit dem nächsten Schritt fortfahren.

Controller, Ansichten und Routen

Für diese Demo benötigen wir nur einen Controller, um Fotos zu verwalten. Die index-Seite dient als Root:

pages_controller.rb

Die Aussicht:

views/photos/index.html.erb

Zum Rendern des @photos-Arrays ist ein Teil erforderlich:

views/photos/_photo.html.erb

image_data? ist eine von Shrine vorgestellte Methode, die prüft, ob ein Datensatz ein Bild enthält.

image_url ist eine weitere Shrine-Methode, die einfach einen Pfad zum Originalbild zurückgibt. Natürlich ist es viel besser, stattdessen ein kleines Miniaturbild anzuzeigen, aber wir werden uns später darum kümmern.

Fügen Sie alle erforderlichen Routen hinzu:

config/routes.rb

Das ist es - die Grundlagen sind getan, und wir können mit dem interessanten Teil fortfahren!

Dateien hochladen

In diesem Abschnitt werde ich Ihnen zeigen, wie Sie die Funktionalität zum tatsächlichen Hochladen von Dateien hinzufügen. Die Controller-Aktionen sind sehr einfach:

photos_controller.rb

Das einzige Problem ist, dass Sie für starke Parameter das virtuelle image-Attribut und nicht die image_data zulassen müssen.

photos_controller.rb

Erstellen Sie die new Ansicht:

views/photos/new.html.erb

Der Teil des Formulars ist ebenfalls trivial:

views/photos/_form.html.erb

Beachten Sie erneut, dass wir das image-Attribut verwenden, nicht die image_data.

Fügen Sie zum Schluss einen weiteren Teil hinzu, um Fehler anzuzeigen:

views/shared/_errors.html.erb

Das ist so ziemlich alles - Sie können sofort mit dem Hochladen von Bildern beginnen.

Validierungen

Natürlich muss noch viel Arbeit geleistet werden, um die Demo-App zu vervollständigen. Das Hauptproblem besteht darin, dass die Benutzer absolut jeden Dateityp mit jeder Größe hochladen können, was nicht besonders groß ist. Fügen Sie daher ein weiteres Plugin hinzu, um Validierungen zu unterstützen:

config/inititalizers/shrine.rb

Richten Sie die Validierungslogik für den ImageUploader ein:

models/image_uploader.rb

Ich erlaube nur das Hochladen von JPG- und PNG-Bildern mit weniger als 1 MB. Passen Sie diese Regeln nach Belieben an.

MIME-Typen

Ein weiterer wichtiger Punkt ist, dass Shrine standardmäßig den MIME-Typ einer Datei mithilfe des HTTP-Headers für den Inhaltstyp ermittelt. Dieser Header wird vom Browser übergeben und nur basierend auf der Dateierweiterung festgelegt, was nicht immer wünschenswert ist.

Wenn Sie den MIME-Typ basierend auf dem Inhalt der Datei bestimmen möchten, verwenden Sie ein Plugin namens determine_mime_type. Ich werde es in die Uploader-Klasse aufnehmen, da andere Modelle diese Funktionalität möglicherweise nicht benötigen:

models/image_uploader.rb

Dieses Plugin verwendet standardmäßig das Linux-Dateidienstprogramm.

Angehängte Bilder zwischenspeichern

Wenn ein Benutzer ein Formular mit falschen Daten sendet, wird das Formular derzeit erneut mit den oben gerenderten Fehlern angezeigt. Das Problem ist jedoch, dass das angehängte Bild verloren geht und der Benutzer es erneut auswählen muss. Dies lässt sich sehr einfach mit einem weiteren Plugin namens cached_attachment_data beheben:

models/image_uploader.rb

Fügen Sie jetzt einfach ein verstecktes Feld in Ihr Formular ein.

views/photos/_form.html.erb

Bearbeiten eines Fotos

Jetzt können Bilder hochgeladen werden, aber es gibt keine Möglichkeit, sie zu bearbeiten. Lassen Sie es uns also sofort beheben. Die Aktionen des entsprechenden Controllers sind etwas trivial:

photos_controller.rb

Der gleiche _form-Teil wird verwendet:

views/photos/edit.html.erb

Schön, aber nicht genug: Benutzer können ein hochgeladenes Bild immer noch nicht entfernen. Um dies zu ermöglichen, benötigen wir - raten Sie mal - ein weiteres Plugin:

models/image_uploader.rb

Es verwendet ein virtuelles Attribut mit dem Namen :remove_image. Lassen Sie es also im Controller zu:

photos_controller.rb

Zeigen Sie jetzt einfach ein Kontrollkästchen an, um ein Bild zu entfernen, wenn in einem Datensatz ein Anhang vorhanden ist:

views/photos/_form.html.erb

Generieren eines Miniaturbilds

Derzeit werden Originalbilder angezeigt. Dies ist nicht der beste Ansatz für die Vorschau: Fotos sind möglicherweise groß und nehmen zu viel Platz ein. Natürlich können Sie einfach die CSS-Attribute width und height verwenden, aber das ist auch eine schlechte Idee. Sie sehen, auch wenn das Bild mithilfe von Stilen klein eingestellt ist, muss der Benutzer die Originaldatei herunterladen, die möglicherweise ziemlich groß ist.

Daher ist es viel besser, beim ersten Upload ein kleines Vorschaubild auf der Serverseite zu generieren. Dies beinhaltet zwei Plugins und zwei zusätzliche Edelsteine. Lassen Sie zuerst die Edelsteine fallen:

Image_processing ist ein besonderes Juwel, das vom Autor von Shrine erstellt wurde. Es werden einige allgemeine Hilfsmethoden zum Bearbeiten von Bildern vorgestellt. Dieses Juwel wiederum basiert auf mini_magick, einem Ruby-Wrapper für ImageMagick. Wie Sie vermutet haben, benötigen Sie ImageMagick auf Ihrem System, um diese Demo ausführen zu können.

Installiere diese neuen Edelsteine:

Fügen Sie nun die Plugins zusammen mit ihren Abhängigkeiten hinzu:

models/image_uploader.rb

Die Verarbeitung ist das Plugin, mit dem ein Bild tatsächlich bearbeitet werden kann (z. B. verkleinern, drehen, in ein anderes Format konvertieren usw.). Versionen wiederum ermöglichen es uns, ein Bild in verschiedenen Varianten zu haben. Für diese Demo werden zwei Versionen gespeichert: "Original" und "Daumen" (Größe auf 300x300 geändert).

Hier ist der Code zum Verarbeiten eines Bildes und Speichern seiner zwei Versionen:

models/image_uploader.rb

resize_to_limit! ist eine Methode, die vom Juwel image_processing bereitgestellt wird. Es verkleinert ein Bild einfach auf 300 x 300, wenn es größer ist, und macht nichts, wenn es kleiner ist. Darüber hinaus bleibt das ursprüngliche Seitenverhältnis erhalten.

Wenn Sie das Bild jetzt anzeigen, müssen Sie nur noch das Argument :original oder :thumb für die image_url-Methode angeben:

views/photos/_photo.html.erb

Das gleiche kann innerhalb des Formulars gemacht werden:

views/photos/_form.html.erb

Um die verarbeiteten Dateien nach Abschluss des Uploads automatisch zu löschen, können Sie ein Plugin namens delete_raw hinzufügen:

models/image_uploader.rb

Metadaten des Bildes

Neben dem tatsächlichen Rendern eines Bildes können Sie auch dessen Metadaten abrufen. Lassen Sie uns zum Beispiel die Größe und den MIME-Typ des Originalfotos anzeigen:

views/photos/_photo.html.erb

Was ist mit seinen Dimensionen? Leider werden sie nicht standardmäßig gespeichert, dies ist jedoch mit einem Plugin namens store_dimensions möglich.

Bildabmessungen

Das store_dimensions-Plugin basiert auf dem Fastimage-gem. Schließen Sie es jetzt an:

Vergiss nicht zu rennen:

Fügen Sie jetzt einfach das Plugin hinzu:

models/image_uploader.rb

Und zeigen Sie die Abmessungen mit den Methoden width und height an:

views/photos/_photo.html.erb

Außerdem steht eine dimensions-Methode zur Verfügung, die ein Array mit Breite und Höhe zurückgibt (z. B. [500, 750]).

Umzug in die Cloud

Entwickler wählen häufig Cloud-Dienste, um hochgeladene Dateien zu hosten, und Shrine bietet eine solche Möglichkeit. In diesem Abschnitt werde ich Ihnen zeigen, wie Sie Dateien auf Amazon S3 hochladen.

Fügen Sie als ersten Schritt zwei weitere Edelsteine in die Gemfile ein:

aws-sdk ist erforderlich, um mit dem SDK von S3 zu arbeiten, während dotenv-rails zum Verwalten von Umgebungsvariablen in der Entwicklung verwendet werden.

Bevor Sie fortfahren, sollten Sie ein Schlüsselpaar für den Zugriff auf S3 über die API erhalten. Melden Sie sich bei Amazon Web Services Console an (oder melden Sie sich an) und navigieren Sie zu Sicherheitsanmeldeinformationen > Benutzer. Erstellen Sie einen Benutzer mit Berechtigungen zum Bearbeiten von Dateien in S3. Hier ist die einfache Richtlinie, die den vollständigen Zugriff auf S3 darstellt:

Laden Sie das Schlüsselpaar des erstellten Benutzers herunter. Alternativ können Sie Root-Zugriffsschlüssel verwenden, aber ich rate Ihnen dringend davon ab, da dies sehr unsicher ist.

Erstellen Sie als Nächstes einen S3-Bucket zum Hosten Ihrer Dateien und fügen Sie eine Datei zum Stammverzeichnis des Projekts hinzu, um Ihre Konfiguration zu hosten:

.env

Stellen Sie diese Datei niemals der Öffentlichkeit zur Verfügung und schließen Sie sie von Git aus:

.gitignore

Ändern Sie nun die globale Konfiguration von Shrine und führen Sie einen neuen Speicher ein:

config/initializers/shrine.rb

Das ist es! An den anderen Teilen der App müssen keine Änderungen vorgenommen werden, und Sie können diesen neuen Speicher sofort testen. Wenn Sie von S3 Fehler im Zusammenhang mit falschen Schlüsseln erhalten, stellen Sie sicher, dass Sie den Schlüssel und das Geheimnis korrekt kopiert haben, ohne Leerzeichen und unsichtbare Sonderzeichen.

Abschluss

Wir sind am Ende dieses Artikels angelangt. Hoffentlich fühlen Sie sich inzwischen sehr sicher, Shrine zu verwenden, und möchten es gerne in einem Ihrer Projekte einsetzen. Wir haben viele Funktionen dieses Edelsteins besprochen, aber es gibt noch mehr, wie die Möglichkeit, zusätzlichen Kontext zusammen mit Dateien zu speichern, und den direkten Upload-Mechanismus.

Durchsuchen Sie daher die Dokumentation von Shrine und die offizielle Website, auf der alle verfügbaren Plugins ausführlich beschrieben werden. Wenn Sie noch Fragen zu diesem Juwel haben, zögern Sie nicht, diese zu posten. Ich danke Ihnen, dass Sie bei mir geblieben sind, und wir sehen uns 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.