Vor einiger Zeit schrieb ich einen Artikel zum Hochladen von Dateien mit Rails und Shrine, in dem erklärt wurde, wie Sie mit Hilfe des Shrine-Gems eine Funktion zum Hochladen von Dateien in Ihre Rails-Anwendung einführen. Es gibt jedoch eine Reihe ähnlicher Lösungen, und Dragonfly ist eine meiner Favoriten, eine benutzerfreundliche Upload-Lösung für Rails und Rack, die von Mark Evans erstellt wurde.
Wir haben diese Bibliothek Anfang letzten Jahres behandelt, aber wie bei der meisten Software hilft es auch, Bibliotheken von Zeit zu Zeit zu betrachten, 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 erläutern, wie die Hauptfunktionen von Dragonfly genutzt werden. Du wirst lernen wie:
Um die Dinge interessanter zu machen, erstellen wir eine kleine musikalische Anwendung. Es werden Alben und zugehörige Songs präsentiert, die auf der Website verwaltet und wiedergegeben werden können.
Der Quellcode für diesen Artikel ist bei GitHub verfügbar. Sie können auch die Funktionsdemo der Anwendung überprüfen.
Erstellen Sie zunächst eine neue Rails-Anwendung ohne die Standard-Testsuite:
Schienen neu UploadingWithDragonfly -T
Für diesen Artikel werde ich Rails 5 verwenden, die meisten der beschriebenen Konzepte gelten jedoch auch für ältere Versionen.
Unsere kleine Musikseite wird zwei Modelle enthalten: Album
und Lied
. Zunächst erstellen wir die erste mit den folgenden Feldern:
Titel
(Schnur
) - enthält den Titel des AlbumsSänger
(Schnur
) -Album's Performerimage_uid
(Schnur
) -ein spezielles Feld zum Speichern des Vorschaubildes des Albums. Dieses Feld kann beliebig benannt werden, muss aber das enthalten _uid
Suffix wie in der Dragonfly-Dokumentation beschrieben.Erstellen Sie die entsprechende Migration und wenden Sie sie an:
Schienen g Modell Albumtitel: Zeichenfolge Sänger: Zeichenfolge image_uid: Zeichenfolge Schienen db: migrate
Nun erstellen wir einen sehr generischen Controller, um Alben mit allen Standardaktionen zu verwalten:
Klasse AlbenController < ApplicationController def index @albums = Album.all end def show @album = Album.find(params[:id]) end def new @album = Album.new end def create @album = Album.new(album_params) if @album.save flash[:success] = 'Album added!' redirect_to albums_path else render :new end end def edit @album = Album.find(params[:id]) end def update @album = Album.find(params[:id]) if @album.update_attributes(album_params) flash[:success] = 'Album updated!' redirect_to albums_path else render :edit end end def destroy @album = Album.find(params[:id]) @album.destroy flash[:success] = 'Album removed!' redirect_to albums_path end private def album_params params.require(:album).permit(:title, :singer) end end
Fügen Sie schließlich die Routen hinzu:
Quellen: Alben
Es ist Zeit für Dragonfly, ins Rampenlicht zu treten. Fügen Sie zuerst den Edelstein in die hinzu Gemfile:
Juwel 'Libelle'
Lauf:
Bündel Installationsschienen erzeugen Libelle
Der letztere Befehl erstellt einen Initialisierer namens dragonfly.rb mit der Standardkonfiguration. Wir werden es vorerst beiseite legen, aber Sie können auf der offiziellen Website von Dragonfly verschiedene Optionen nachlesen.
Als Nächstes müssen Sie unser Modell mit den Methoden von Dragonfly ausstatten. Dies geschieht mit der dragonfly_accessor
:
dragonfly_accessor: Bild
Beachten Sie, dass ich hier sage :Bild
-es bezieht sich direkt auf die image_uid
Spalte, die wir im vorherigen Abschnitt erstellt haben. Wenn Sie beispielsweise Ihre Spalte benannt haben photo_uid
, dann ist die dragonfly_accessor
Methode müsste erhalten :Foto
als Argument.
Wenn Sie Rails 4 oder 5 verwenden, ist ein weiterer wichtiger Schritt das Markieren der :Bild
Feld (nicht : image_uid
!) wie in der Steuerung erlaubt:
params.require (: album) .permit (: Titel,: Sänger,: Bild)
Das ist so ziemlich alles - wir sind bereit, Ansichten zu erstellen und mit dem Hochladen unserer Dateien zu beginnen!
Beginnen Sie mit der Indexansicht:
Alben
<%= link_to 'Add', new_album_path %>
Nun das partielle:
Hier sind zwei Libellenmethoden 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 Seiten und die Bearbeitungsseiten hinzu:
Album hinzufügen
<%= render 'form' %>
Bearbeiten <%= @album.title %>
<%= render 'form' %>
<%= form_for @album do |f| %><%= f.label :title %> <%= f.text_field :title %><%= f.label :singer %> <%= f.text_field :singer %><%= f.label :image %> <%= f.file_field :image %><%= f.submit %> <% end %>
Die Form ist nichts Besonderes, aber beachten Sie noch einmal, dass wir sagen :Bild
, nicht : image_uid
, beim Rendern der Dateieingabe.
Jetzt können Sie den Server starten und die Upload-Funktion testen!
Die Benutzer können also Alben erstellen und bearbeiten, es gibt jedoch ein Problem: Sie haben keine Möglichkeit, ein Bild zu entfernen, sondern nur durch ein anderes zu ersetzen. Zum Glück ist dies sehr einfach zu beheben, indem ein Kontrollkästchen "Bild entfernen" eingefügt wird:
<% if @album.image_thumb_stored? %> <%= image_tag(@album.image.url, alt: @album.title) %> <%= f.label :remove_image %> <%= f.check_box :remove_image %> <% end %>
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 das, wenn Ihr Feld benannt ist photo_uid
, dann wird die entsprechende Methode zum Entfernen von Anhängen sein Foto entfernen
. Einfach ist es nicht?
Die einzige andere Sache, die man tun kann, ist das zuzulassen entferne Bild
Attribut in Ihrem Controller:
params.require (: album) .permit (: Titel,: Sänger,: Bild,: remove_image)
Zum jetzigen Zeitpunkt funktioniert alles gut, aber wir prüfen die Eingaben des Benutzers überhaupt nicht, was nicht besonders großartig ist. Fügen wir daher Validierungen für das Album-Modell hinzu:
validiert: Titel, Präsenz: true validiert: Sänger, Präsenz: true validiert: Bild, Präsenz: true validates_property: width, of:: image, in: (0… 900)
validates_property
ist die Dragonfly - Methode, mit der Sie verschiedene Aspekte Ihres Anhangs prüfen können: Sie können die Dateierweiterung, den MIME - Typ, die Größe usw. überprüfen.
Nun erstellen wir ein generisches Partial, um die gefundenen Fehler zu rendern:
<% if object.errors.any? %><% end %>Die folgenden Fehler wurden gefunden:
<% object.errors.full_messages.each do |msg| %>
- <%= msg %>
<% end %>
Verwenden Sie diesen Teil innerhalb des Formulars:
<%= form_for @album do |f| %> <%= render 'shared/errors', object: @album %> <%#… %> <% end %>
Gestalten Sie die Felder ein wenig mit Fehlern, um sie visuell darzustellen:
.field_with_errors display: inline; Beschriftung Farbe: Rot; input Hintergrundfarbe: lightpink;
Nachdem Validierungen eingeführt wurden, stoßen wir auf ein weiteres Problem (ein recht typisches Szenario, oder?): Wenn der Benutzer beim Ausfüllen des Formulars Fehler gemacht hat, muss er die Datei nach dem Klicken auf erneut auswählen einreichen Taste.
Dragonfly kann Ihnen auch helfen, dieses Problem zu lösen, indem Sie a verwenden einbehalten_ *
verstecktes Feld:
<%= f.hidden_field :retained_image %>
Vergiss nicht, auch dieses Feld zuzulassen:
params.require (: album) .permit (: Titel,: Sänger,: Bild,: remove_image,: retention_image)
Jetzt bleibt das Bild zwischen den Anfragen bestehen! Das einzige kleine Problem ist jedoch, dass in der Dateiuploadeingabe immer noch die Meldung "Choose a file" angezeigt wird. Dies kann jedoch durch ein wenig Styling und ein wenig JavaScript behoben werden.
Die von unseren Benutzern hochgeladenen Bilder können sehr unterschiedliche Abmessungen haben, was sich negativ auf das Design der Website auswirken kann (und dies wahrscheinlich auch sein wird). Wahrscheinlich möchten Sie die Bilder auf einige feste Dimensionen verkleinern. Dies ist natürlich möglich, indem Sie die Breite
und Höhe
Stile. Dies ist jedoch kein optimaler Ansatz: Der Browser muss immer noch Bilder in voller Größe herunterladen und sie dann verkleinern.
Eine andere Option (die in der Regel viel besser ist) ist das Erstellen von Miniaturbildern mit vordefinierten Abmessungen auf dem Server. Mit Dragonfly ist das ganz einfach zu erreichen:
250 x 250
ist natürlich die Abmessungen, während #
ist die Geometrie, die "Größenänderung und Zuschnitt, falls erforderlich, um das Seitenverhältnis mit Schwerpunktsschwerpunkt einzuhalten" bedeutet. Informationen zu anderen Geometrien finden Sie auf der Website von Dragonfly.
Das Daumen
Die Methode basiert auf ImageMagick - eine großartige Lösung zum Erstellen und Bearbeiten von Bildern. Um die funktionsfähige Demo lokal anzuzeigen, müssen Sie ImageMagick installieren (alle gängigen Plattformen werden unterstützt)..
Die Unterstützung für ImageMagick ist im Initialisierungsprogramm von Dragonfly standardmäßig aktiviert:
Plugin: Imagemagick
Jetzt werden Miniaturansichten erstellt, die jedoch nirgendwo gespeichert werden. Dies bedeutet, dass jedes Mal, wenn ein Benutzer die Albumseite besucht, die Miniaturansichten neu erstellt werden. Es gibt zwei Möglichkeiten, um dieses Problem zu überwinden: durch Generieren nach dem Speichern des Datensatzes oder durch sofortige Generierung.
Die erste Option besteht darin, eine neue Spalte einzuführen, um die Miniaturansicht zu speichern und die dragonfly_accessor
Methode. Erstellen Sie eine neue Migration und wenden Sie sie an:
Schienen g Migration add_image_thumb_uid_to_albums image_thumb_uid: String Schienen db: migrate
Ändern Sie nun das Modell:
dragonfly_accessor: image do copy_to (: image_thumb) | a | a.thumb ('250x250 #') end dragonfly_accessor: image_thumb
Beachten Sie, dass jetzt der erste Anruf an dragonfly_accessor
sendet einen Block, der das Miniaturbild tatsächlich für uns generiert und in das Archiv kopiert image_thumb
. Verwenden Sie jetzt einfach die image_thumb
Methode in Ihren Ansichten:
<%= image_tag(album.image_thumb.url, alt: album.title) if album.image_thumb_stored? %>
Diese Lösung ist die einfachste, wird aber von den offiziellen Dokumenten nicht empfohlen und, was noch schlimmer ist, zum Zeitpunkt des Schreibens funktioniert sie nicht mit einbehalten_ *
Felder.
Lassen Sie mich daher eine weitere Option anzeigen: das Erstellen von Miniaturbildern im laufenden Betrieb. Dazu müssen Sie ein neues Modell erstellen und die Konfigurationsdatei von Dragonfly anpassen. Zuerst das Modell:
Schienen g Modell Thumb uid: string job: string rake db: migrieren
Das Daumen
Die Tabelle wird Ihre Miniaturansichten aufnehmen, sie werden jedoch bei Bedarf generiert. Damit dies geschehen kann, müssen wir das neu definieren url
Methode im Dragonfly-Initialisierer:
Dragonfly.app.configure do define_url do | app, job, opts | thumb = Thumb.find_by_job (job.signature) if thumb app.datastore.url_for (thumb.uid,: scheme => 'https'), andernfalls app.server.url_for (job) end end vor_serve do | job, env | uid = job.store Thumb.create! (: uid => uid,: job => job.signature) end #… end
Fügen Sie nun ein neues Album hinzu und besuchen Sie die Hauptseite. Beim ersten Mal wird die folgende Ausgabe in die Protokolle gedruckt:
DRAGONFLY: Shell-Befehl: "convert" "some_path / public / system / libelle / development / 2017/02/08 / 3z5p5nvbmx_Folder.jpg" "-resize" "250x250 ^" "-gravity" "Center" "-crop" " 250x250 + 0 + 0 "+ repage" "some_path / 20170208-1692-1xrqzc9.jpg"
Dies bedeutet effektiv, dass das Miniaturbild von ImageMagick für uns generiert wird. Wenn Sie die Seite neu laden, wird diese Zeile jedoch nicht mehr angezeigt, was bedeutet, dass die Miniaturansicht zwischengespeichert wurde. Sie können etwas mehr über diese Funktion auf der Dragonfly-Website nachlesen.
Sie können Ihre Bilder praktisch beliebig bearbeiten, nachdem sie hochgeladen wurden. Dies kann in der getan werden after_assign
Ruf zurück. Lassen Sie uns beispielsweise alle unsere Bilder mit 90% Qualität in das JPEG-Format konvertieren:
dragonfly_accessor: image do after_assign | a | a.encode! ('jpg', '-qualitat 90') ende
Es gibt viele weitere Aktionen, die Sie ausführen können: Drehen und Zuschneiden der Bilder, Kodieren mit einem anderen Format, Schreiben von Text, Mischen mit anderen Bildern (z. B. zum Platzieren eines Wasserzeichens) usw. Weitere Beispiele finden Sie unter den ImageMagick-Bereich auf der Dragonfly-Website.
Natürlich besteht der Hauptteil unserer musikalischen Site aus Liedern, also fügen wir sie jetzt hinzu. Jeder Song hat einen Titel und eine Musikdatei und gehört zu einem Album:
Schienen g Modell Songalbum: Gehört zu: Titel: String Track_uid: String Rails db: migrate
Schließen Sie die Dragonfly-Methoden an, wie wir es für das getan haben Album
Modell:
dragonfly_accessor: track
Vergiss nicht, eine hat viele
Beziehung:
has_many: lieder, abhängig:: zerstören
Neue Routen hinzufügen Ein Song existiert immer im Rahmen eines Albums, daher werde ich diese Routen verschachteln:
Ressourcen: Alben tun Ressourcen: Lieder, nur: [: neu,: erstellen] Ende
Erstellen Sie einen sehr einfachen Controller (vergessen Sie nicht, das zuzulassen.) Spur
Feld):
Klasse SongsController < ApplicationController def new @album = Album.find(params[:album_id]) @song = @album.songs.build end def create @album = Album.find(params[:album_id]) @song = @album.songs.build(song_params) if @song.save flash[:success] = "Song added!" redirect_to album_path(@album) else render :new end end private def song_params params.require(:song).permit(:title, :track) end end
Zeigen Sie die Lieder und einen Link an, um einen neuen hinzuzufügen:
<%= @album.title %>
durch <%= @album.singer %>
<%= link_to 'Add song', new_album_song_path(@album) %><%= render @album.songs %>
Geben Sie das Formular ein:
Lied zu hinzufügen <%= @album.title %>
<%= form_for [@album, @song] do |f| %><%= f.label :title %> <%= f.text_field :title %><%= f.label :track %> <%= f.file_field :track %><%= f.submit %> <% end %>
Zuletzt fügen Sie die _Lied teilweise:
Hier verwende ich das HTML5 Audio-
Tag, das für ältere Browser nicht funktioniert. Wenn Sie solche Browser unterstützen möchten, verwenden Sie eine 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
Fügen Sie ein geeignetes Feld hinzu, lassen Sie es zu und rendern Sie ein Dateieingabe-Tag.
Wenn ich eine Wiedergabeliste öffne, erhalte ich zusätzliche Informationen zu jedem Song, z. B. Dauer und Bitrate. Diese Informationen werden standardmäßig nicht überall gespeichert, aber wir können das ganz leicht beheben. Dragonfly ermöglicht es uns, zusätzliche Daten zu jeder hochgeladenen Datei bereitzustellen und diese später mit Hilfe der Meta
Methode.
Die Dinge sind jedoch etwas komplexer, wenn wir mit Audio oder Video arbeiten, da zum Abrufen ihrer Metadaten ein spezielles Streamio-ffmpeg benötigt wird. Dieses Juwel wiederum ist auf FFmpeg angewiesen. Um fortfahren zu können, müssen Sie es auf Ihrem PC installieren.
Hinzufügen Streamio-ffmpeg
in die Gemfile:
gem 'streamio-ffmpeg'
Es installieren:
Bundle installieren
Jetzt können wir dasselbe einsetzen after_assign
Rückruf bereits in den vorherigen Abschnitten gesehen:
dragonfly_accessor: track do after_assign do | a | song = FFMPEG :: Movie.new (a.path) mm, ss = song.duration.divmod (60) .map | n | n.to_i.to_s.rjust (2, '0') a.meta ['duration'] = "# mm: # ss" a.meta ['bitrate'] = song.bitrate? song.bitrate / 1000: 0 end end
Beachten Sie, dass ich hier eine Pfad
Methode nicht url
, denn an dieser stelle arbeiten wir mit einem tempfile. Als nächstes extrahieren wir einfach die Dauer des Songs (Umwandlung in Minuten und Sekunden mit führenden Nullen) und die Bitrate (Umwandlung in Kilobytes pro Sekunde)..
Zeigen Sie zuletzt Metadaten in der Ansicht an:
Wenn Sie den Inhalt des überprüfen öffentlich / system / libelle Ordner (der Standardspeicherort für die Uploads) .yml Dateien - sie speichern alle Metainformationen im YAML-Format.
Das letzte Thema, das wir heute behandeln werden, ist die Vorbereitung Ihrer Anwendung vor der Bereitstellung auf der Heroku Cloud-Plattform. Das Hauptproblem ist, dass Heroku das Speichern von benutzerdefinierten Dateien (wie Uploads) nicht zulässt. Daher müssen wir auf einen Cloud-Speicherdienst wie Amazon S3 zurückgreifen. Zum Glück lässt sich Dragonfly problemlos integrieren.
Alles, was Sie tun müssen, ist, ein neues Konto bei AWS zu registrieren (sofern Sie noch nicht über dieses Konto verfügen), einen Benutzer mit der Berechtigung zum Zugriff auf S3-Buckets zu erstellen und das Schlüsselpaar des Benutzers an einem sicheren Ort aufzuschreiben. Sie können ein Schlüsselpaar verwenden, aber das ist wirklich der Fall nicht empfohlen. Erstellen Sie schließlich einen S3-Bucket.
Gehen Sie zurück zu unserer Rails-Anwendung und werfen Sie einen neuen Edelstein:
Gruppe: Produktion do Gem 'dragonfly-s3_data_store' Ende
Es installieren:
Bundle installieren
Passen Sie dann die Konfiguration von Dragonfly an, um S3 in einer Produktionsumgebung zu verwenden:
wenn Rails.env.production? datastore: s3, bucket_name: ENV ['S3_BUCKET'], access_key_id: ENV ['S3_KEY'], secret_access_key: ENV ['S3_SECRET'], Region: ENV ['S3_REGION'], url_scheme: 'https' else datastore: datei, root_path: Rails.root.join ('public / system / dragonfly', Rails.env), server_root: Rails.root.join ('public') enden
Bereitstellen ENV
Variablen auf Heroku verwenden Sie diesen Befehl:
heroku config: addiere SOME_KEY = SOME_VALUE
Wenn Sie die Integration mit S3 lokal testen möchten, können Sie zum Verwalten von Umgebungsvariablen einen Edelstein wie dotenv-rail verwenden. Denken Sie jedoch daran, dass Ihr AWS-Schlüsselpaar darf nicht öffentlich ausgesetzt werden!
Ein weiteres kleines Problem, dem ich bei der Bereitstellung bei Heroku begegnet bin, war das Fehlen von FFmpeg. Wenn eine neue Heroku-Anwendung erstellt wird, verfügt sie über eine Reihe von Diensten, 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:
Heroku-Buildpacks: Fügen Sie https://github.com/HYPERHYPER/heroku-buildpack-ffmpeg.git hinzu
Jetzt ist alles fertig und Sie können Ihre Musikanwendung mit der Welt teilen!
Das war eine lange Reise, oder? Heute haben wir über Dragonfly diskutiert - eine Lösung für das Hochladen von Dateien in Rails. Wir haben die Grundeinstellungen, einige Konfigurationsoptionen, die Erzeugung von Miniaturansichten, die Verarbeitung und das Speichern von Metadaten kennen gelernt. 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. Besuchen Sie daher die offizielle Website, um ausführliche Dokumentation und nützliche Beispiele zu finden. Wenn Sie weitere Fragen haben oder einige Code-Beispiele haben, zögern Sie nicht, mich zu kontaktieren.
Vielen Dank, dass Sie bei mir geblieben sind, und bis bald!