Dies ist ein weiterer Artikel aus der Reihe "Uploading with Rails". Heute treffen wir uns mit Carrierwave, einer der beliebtesten Lösungen für das Hochladen von Dateien für Rails. Ich mag Carrierwave, weil es einfach ist, anzufangen, es bietet viele Funktionen und ist mit Dutzenden von Anleitungen ausgestattet, die von den Mitgliedern der Community geschrieben werden, damit Sie nicht verloren gehen.
In diesem Artikel erfahren Sie, wie Sie:
Der Quellcode für diesen Artikel ist auf GitHub verfügbar. Viel Spaß beim Lesen!
Erstellen Sie wie immer eine neue Rails-Anwendung:
Schienen neu UploadingWithCarrierwave -T
Für diese Demo verwende ich Rails 5.0.2. Bitte beachten Sie, dass Carrierwave 1 nur Rails 4+ und Ruby 2 unterstützt. Wenn Sie noch auf Rails 3 fahren, schließen Sie die Carrierwave-Version 0.11 an.
Um Carrierwave in Aktion zu sehen, erstellen wir eine sehr einfache Blogging-Anwendung mit einer Sohle Post
Modell. Es wird die folgenden Hauptattribute haben:
Titel
(Schnur
)Karosserie
(Text
)Bild
(Schnur
) -dieses Feld enthält ein Bild (genauer gesagt der Dateiname), das an den Beitrag angehängt wirdGenerieren und wenden Sie eine neue Migration an:
Schienen g Modell Beitragstitel: String Body: Textbild: String Schienen db: migrieren
Einige Routen einrichten:
Quellen: Beiträge root: 'posts # index'
Erstellen Sie außerdem einen sehr einfachen Controller:
Klasse PostsController < ApplicationController before_action :set_post, only: [:show, :edit, :update] def index @posts = Post.order('created_at DESC') end def show end def new @post = Post.new end def create @post = Post.new(post_params) if @post.save redirect_to posts_path else render :new end end def edit end def update if @post.update_attributes(post_params) redirect_to post_path(@post) else render :edit end end private def post_params params.require(:post).permit(:title, :body, :image) end def set_post @post = Post.find(params[:id]) end end
Lass uns jetzt das machen Index Aussicht:
Beiträge
<%= link_to 'Add post', new_post_path %> <%= render @posts %>
Und der entsprechende Teil:
<%= link_to post.title, post_path(post) %>
<%= truncate(post.body, length: 150) %>
<%= link_to 'Edit', edit_post_path(post) %>
Hier benutze ich die Rails kürzen
Methode, um nur die ersten 150 Symbole des Beitrags anzuzeigen. Bevor wir andere Ansichten und Formulare erstellen, integrieren wir zunächst Carrierwave in die Anwendung.
Legen Sie einen neuen Edelstein in die Gemfile:
gem 'carrierwave', '~> 1.0'
Lauf:
Bundle installieren
Carrierwave speichert seine Konfiguration darin Uploader die in Ihren Modellen enthalten sind. Verwenden Sie zum Generieren eines Uploaders den folgenden Befehl:
Schienen erzeugen Uploader Image
Nun drinnen App / Uploader, Sie finden eine neue Datei namens image_uploader.rb. Beachten Sie, dass es einige nützliche Kommentare und Beispiele enthält, so dass Sie damit beginnen können. In dieser Demo werden wir ActiveRecord verwenden, aber Carrierwave unterstützt auch Mongoid, Sequel und DataMapper.
Als nächstes müssen wir oder einschließen montieren diesen Uploader in das Modell:
mount_uploader: Bild, ImageUploader
Der Uploader hat bereits normale Standardeinstellungen, aber zumindest müssen wir auswählen, wo die hochgeladenen Dateien gespeichert werden. Jetzt setzen wir den Dateispeicher ein:
Speicher: Datei
Standardmäßig werden Dateien in der öffentlich / Uploads Verzeichnis, so dass es am besten aus dem Versionskontrollsystem ausgeschlossen wird:
öffentlich / Uploads
Sie können auch das ändern store_dir
Methode in Ihrem Uploader, um einen anderen Speicherort auszuwählen.
An dieser Stelle können wir eine neue Ansicht und ein Formular erstellen, um Dateien hochzuladen:
Beitrag hinzufügen
<%= render 'form', post: @post %>
<%= form_for post do |f| %><%= f.label :title %> <%= f.text_field :title %><%= f.label :body %> <%= f.text_area :body %><%= f.label :image %> <%= f.file_field :image %><%= f.submit %> <% end %>
Notiere dass der PostsController
muss nicht geändert werden, da wir das bereits erlaubt haben Bild
Attribut.
Zuletzt erstellen Sie die Bearbeitungsansicht:
Beitrag bearbeiten
<%= render 'form', post: @post %>
Das ist es! Sie können den Server starten und versuchen, einen Beitrag mit einem Image zu erstellen. Das Problem ist, dass dieses Bild nirgendwo sichtbar ist. Fahren wir mit dem nächsten Abschnitt fort und fügen Sie eine Show-Seite hinzu!
Die einzige Ansicht, die wir noch nicht erstellt haben, ist also Show. Jetzt hinzufügen:
<%= link_to 'All posts', posts_path %><%= @post.title %>
<%= image_tag(@post.image.url, alt: 'Image') if @post.image? %><%= @post.body %>
<%= link_to 'Edit', edit_post_path(@post) %>
Wie Sie sehen, ist das Anzeigen eines Anhangs sehr einfach: Sie müssen nur sagen @ post.image.url
um die URL eines Bildes zu packen. Um einen Pfad zu der Datei zu erhalten, verwenden Sie die current_path
Methode. Beachten Sie, dass Carrierwave auch eine Bild?
Methode, um zu prüfen, ob überhaupt ein Anhang vorhanden ist (der Bild
Methode selbst wird nie zurückkehren Null
, auch wenn die Datei nicht vorhanden ist).
Nachdem Sie zu einem Beitrag navigiert haben, sollten Sie ein Bild sehen, das jedoch möglicherweise zu groß erscheint: Schließlich beschränken wir die Bemaßung nirgendwo. Natürlich hätten wir das Bild mit ein paar CSS-Regeln verkleinern können, aber es ist viel besser, ein Miniaturbild zu erstellen, nachdem die Datei hochgeladen wurde. Dies erfordert jedoch einige zusätzliche Schritte.
Um Bilder zuzuschneiden und zu skalieren, benötigen wir ein separates Werkzeug. Im Auslieferungszustand bietet Carrierwave RMagick- und MiniMagick-Edelsteine an, die wiederum zur Bildbearbeitung mit Hilfe von ImageMagick verwendet werden. ImageMagick ist eine Open-Source-Lösung, mit der Sie vorhandene Bilder bearbeiten und neue erstellen können. Bevor Sie fortfahren, müssen Sie sie herunterladen und installieren. Als nächstes können Sie die beiden Edelsteine auswählen. Ich bleibe bei MiniMagick, weil es viel einfacher zu installieren ist und bessere Unterstützung bietet:
gem 'mini_magick'
Lauf:
Bundle installieren
Dann fügen Sie MiniMagick in Ihren Uploader ein:
umfassen CarrierWave :: MiniMagick
Jetzt müssen wir einfach eine neue Version in unseren Uploader einführen. Das Konzept von Versionen (oder Stile) wird in vielen Bibliotheken zum Hochladen von Dateien verwendet. es bedeutet einfach, dass zusätzliche Dateien, die auf dem ursprünglichen Anhang basieren, beispielsweise mit anderen Abmessungen oder Formaten erstellt werden. Führen Sie eine neue Version ein Daumen
:
version: thumb do process resize_to_fill: [350, 350] end
Sie können so viele Versionen haben, wie Sie möchten. Darüber hinaus können Versionen sogar auf anderen basieren:
version: small_thumb, from_version:: thumb do size resize_to_fill: [20, 20] end
Wenn Sie bereits einige Bilder hochgeladen haben, stehen ihnen keine Miniaturbilder zur Verfügung. Dies ist jedoch kein Problem, da Sie sie von der Rails-Konsole aus neu erstellen können:
Schienen c Post.find_each | post | post.image.recreate_versions! (: thumb) if post.image?
Zuletzt zeigen Sie Ihre Miniaturansicht mit einem Link zum Originalbild an:
<%= link_to(image_tag(@post.image.thumb.url, alt: 'Image'), @post.image.url, target: '_blank') if @post.image? %>
Starten Sie den Server und beobachten Sie das Ergebnis!
Momentan funktioniert unser Upload, aber wir validieren keine Benutzereingaben, was natürlich schlecht ist. Wenn wir nur mit Bildern arbeiten möchten, lassen Sie uns die Erweiterungen .png, .jpg und .gif auf die Whitelist setzen:
def extension_whitelist% w (jpg jpeg gif png) end
Sie können auch Inhaltstypüberprüfungen hinzufügen, indem Sie a definieren content_type_whitelist
Methode:
def content_type_whitelist / image \ // end
Alternativ ist es möglich, einige Dateitypen, z. B. ausführbare Dateien, durch Definieren der Dateierweiterung auf die schwarze Liste zu setzen content_type_blacklist
Methode.
Abgesehen von der Überprüfung von Dateityp und -erweiterung, lassen Sie uns festlegen, dass diese weniger als 1 Megabyte beträgt. Dafür benötigen wir ein zusätzliches Juwel, das Dateivalidierungen für ActiveModel unterstützt:
gem 'file_validators'
Es installieren:
Bundle installieren
Führen Sie nun die gewünschten Validierungen ein (beachten Sie, dass ich auch Checks für das Titel
und Karosserie
Attribute):
validiert: Titel, Präsenz: wahr, Länge: Minimum: 2 validiert: Körper, Präsenz: wahr validiert: Bild, Dateigröße: less_than: 1.Megabytes
Als nächstes müssen Sie I18n-Übersetzungen für die Fehlermeldungen von Carrierwave hinzufügen:
de: errors: messages: carrierwave_processing_error: "Bildgröße kann nicht geändert werden." carrierwave_integrity_error: "Kein Bild." carrierwave_download_error: "Bild konnte nicht heruntergeladen werden." extension_whitelist_error: "Sie dürfen% extension -Dateien nicht hochladen, zulässige Typen:% Allowed_types" extension_blacklist_error: "Sie dürfen keine% extension -Dateien hochladen, verbotene Typen:% verboten_types"
Derzeit zeigen wir keine Validierungsfehler an, also erstellen wir ein gemeinsames Partial:
<% if object.errors.any? %>Einige Fehler wurden gefunden:
Verwenden Sie diesen Teil innerhalb des Formulars:
<%= render 'shared/errors', object: post %>
Versuchen Sie nun einige ungültige Dateien hochzuladen und beobachten Sie das Ergebnis. Es sollte funktionieren, aber wenn Sie eine gültige Datei auswählen und den Titel oder Text nicht ausfüllen, schlagen die Prüfungen immer noch fehl und es wird ein Fehler angezeigt. Das Dateifeld wird jedoch gelöscht, und der Benutzer muss das Bild erneut auswählen, was nicht sehr praktisch ist. Um dies zu beheben, müssen wir dem Formular ein weiteres Feld hinzufügen.
Das Bestehen von Dateien in Formulardarstellungen ist eigentlich ganz einfach. Alles was Sie tun müssen, ist ein neues verstecktes Feld hinzuzufügen und es im Controller zuzulassen:
<%= f.label :image %> <%= f.file_field :image %>
<%= f.hidden_field :image_cache %>
params.require (: post) .permit (: title,: body,: image,: image_cache)
Jetzt die image_cache
wird automatisch ausgefüllt und das Bild geht nicht verloren. Es kann hilfreich sein, auch eine Miniaturansicht anzuzeigen, damit der Benutzer versteht, dass das Bild erfolgreich verarbeitet wurde:
<% if post.image? %> <%= image_tag post.image.thumb.url %> <% end %>
Eine weitere sehr häufige Funktion ist die Möglichkeit, angehängte Dateien beim Bearbeiten eines Datensatzes zu entfernen. Die Implementierung dieser Funktion ist mit Carrierwave kein Problem. Fügen Sie dem Formular ein neues Kontrollkästchen hinzu:
<% if post.image? %> <%= image_tag post.image.thumb.url %><%= label_tag :remove_image do %> Entferne Bild <%= f.check_box :remove_image %> <% end %><% end %>
Und erlaube das entferne Bild
Attribut:
params.require (: post) .permit (: title,: body,: image,: remove_image,: image_cache)
Das ist es! Um ein Bild manuell zu entfernen, verwenden Sie die entferne Bild!
Methode:
@ post.remove_image!
Carrierwave bietet auch eine sehr coole Funktion: die Möglichkeit, Dateien von entfernten Standorten nach ihrer URL hochzuladen. Lassen Sie uns diese Fähigkeit jetzt einführen, indem Sie ein neues Feld hinzufügen und das entsprechende Attribut zulassen:
<%= f.text_field :remote_image_url %> Geben Sie die URL zu einem Bild ein
params.require (: post) .permit (: title,: body,: image,: remove_image,: image_cache,: remote_image_url)
Wie cool ist das? Sie müssen keine Änderungen vornehmen und Sie können diese Funktion sofort testen!
Angenommen, wir möchten, dass unser Posting mehrere Anhänge enthält. Mit dem aktuellen Setup ist dies nicht möglich, aber zum Glück unterstützt Carrierwave ein solches Szenario. Um diese Funktion zu implementieren, müssen Sie entweder ein serialisiertes Feld (für SQLite) oder ein JSON-Feld (für Postgres oder MySQL) hinzufügen. Ich bevorzuge die letztere Option, also wechseln wir jetzt zu einem neuen Datenbankadapter. Entfernen Sie den sqlite3-Edelstein aus dem Gemfile und pg stattdessen hinzufügen:
Juwel 'pg'
Es installieren:
Bundle installieren
Ändern Sie die Datenbankkonfiguration folgendermaßen:
default: & default adapter: postgresql pool: 5 timeout: 5000 entwicklung: <<: *default database: upload_carrier_dev username: 'YOUR_USER' password: 'YOUR_PASSWORD' host: localhost
Erstellen Sie die entsprechende Postgres-Datenbank und generieren Sie die Migration, und wenden Sie sie an:
Schienen g Migration add_attachments_to_posts Anhänge: Json Schienen db: migrieren
Wenn Sie es vorziehen, bei SQLite zu bleiben, befolgen Sie die Anweisungen in der Carrierwave-Dokumentation.
Mounten Sie jetzt die Uploader (beachten Sie die Pluralform!):
mount_uploaders: Anhänge, ImageUploader
Ich verwende denselben Uploader für Anhänge, aber Sie können natürlich einen neuen mit einer anderen Konfiguration generieren.
Fügen Sie das Feld mit mehreren Dateien zu Ihrem Formular hinzu:
<%= f.label :attachments %> <%= f.file_field :attachments, multiple: true %>
Solange die Anlagen
Feld wird ein Array enthalten, es sollte auf folgende Weise erlaubt sein:
params.require (: post) .permit (: title,: body,: image,: remove_image,: image_cache,: remote_image_url, anhänge: [])
Zuletzt können Sie die Anhänge des Beitrags durchlaufen und wie gewohnt anzeigen:
<% if @post.attachments? %>
Beachten Sie, dass jeder Anhang eine Miniaturansicht haben wird, die in unserem Ordner konfiguriert ist ImageUploader
. nett!
Das Speichern von Dateien ist nicht immer bequem und / oder möglich, da beispielsweise auf Heroku keine benutzerdefinierten Dateien gespeichert werden können. Daher könnten Sie sich fragen, wie Sie Carrierwave mit einem Amazon S3-Cloudspeicher verbinden können. Nun, das ist auch eine ziemlich einfache Aufgabe. Carrierwave ist für die Implementierung dieser Funktion auf den Nebel-Aw-Edelstein angewiesen:
gem "fog-aws"
Es installieren:
Bundle installieren
Lassen Sie uns einen Initialisierer für Carrierwave erstellen und den Cloud-Speicher global konfigurieren:
CarrierWave.config do | config | config.fog_provider = 'fog / aws' config.fog_credentials = provider: 'AWS', aws_access_key_id: ENV ['S3_KEY'], aws_secret_access_key: ENV ['S3_SECRET'], region: ENV ['S3_REGION'], config. fog_directory = ENV ['S3_BUCKET'] end
Es gibt einige andere Optionen, die Sie in der Dokumentation finden.
Ich benutze den dotenv-schienen-Edelstein, um die Umgebungsvariablen auf sichere Weise festzulegen, aber Sie können jede andere Option wählen. Stellen Sie jedoch sicher, dass Ihr S3-Schlüsselpaar nicht öffentlich verfügbar ist. Andernfalls kann jeder etwas in Ihren Bucket hochladen!
Als nächstes ersetzen Sie die Speicher: Datei
Zeile mit:
Lagerung: Nebel
Neben S3 unterstützt Carrierwave auch Uploads zu Google Storage und Rackspace. Diese Dienste sind ebenfalls einfach einzurichten.
Das ist es für heute! Wir haben alle wichtigen Funktionen von Carrierwave behandelt und können sie jetzt in Ihren Projekten einsetzen. Es stehen einige zusätzliche Optionen zur Verfügung, also durchsuchen Sie die Dokumentation.
Wenn Sie nicht weiterkommen, zögern Sie nicht, Ihre Fragen zu posten. Es kann auch nützlich sein, einen Blick in das Wiki von Carrierwave zu werfen, in dem nützliche Artikel zum "Wie" gehostet werden, die viele häufig gestellte Fragen beantworten.
Ich danke Ihnen, dass Sie bei mir geblieben sind, und fröhliche Kodierung!