Det finns många filer som laddas upp där som CarrierWave, Paperclip och Dragonfly, för att nämna några. De har alla sina detaljer, och förmodligen har du redan använt minst en av dessa pärlor.
Idag vill jag dock introducera en relativt ny men väldigt cool lösning som heter Shrine, skapad av Janko Marohnić. I motsats till några andra liknande pärlor har den ett modulärt tillvägagångssätt, vilket betyder att varje funktion är packad som en modul (eller plugin i helgedomens terminologi). Vill du stödja valideringar? Lägg till ett plugin. Vill du göra någon filbehandling? Lägg till ett plugin! Jag älskar verkligen detta tillvägagångssätt, eftersom det gör att du enkelt kan styra vilka funktioner som finns tillgängliga för vilken modell.
I den här artikeln ska jag visa dig hur man ska:
Källkoden för den här artikeln finns på GitHub.
Den fungerande demo finns här.
För att starta, skapa en ny Rails-applikation utan standard testpaket:
skenar nytt FileGuru -T
Jag kommer att använda Rails 5 för denna demonstration, men de flesta koncepten gäller även versioner 3 och 4.
Släpp Shrine pärla i din Gemfile:
pärla "helgedom"
Kör sedan:
buntinstallation
Nu behöver vi en modell som jag ska ringa Foto
. Shrine lagrar all filrelaterad information i en särskild textkolumn som slutar med a _data
ändelse. Skapa och tillämpa motsvarande migrering:
skenor g modell Foto titel: sträng image_data: textrader db: migrera
Observera att för äldre versioner av Rails ska det senare kommandot vara:
rake db: migrera
Konfigurationsalternativ för helgedom kan ställas både globalt och per modell. Globala inställningar görs förstås, inuti initialiseringsfilen. Där ska jag ansluta de nödvändiga filerna och plugin-program. Plugins används i Shrine för att extrahera funktionalitet i separata moduler, vilket ger dig fullständig kontroll över alla tillgängliga funktioner. Till exempel finns plugins för validering, bildbehandling, caching-bilagor och mer.
För närvarande lägger vi till två plugins: en för att stödja ActiveRecord och en annan för att ställa in loggning. De kommer att ingå globalt. Ställ också upp filsystemlagring:
kräva "shrine" kräver "shrine / storage / file_system" Shrine.plugin: activiverecord Shrine.plugin: loggar, logger: Rails.logger Shrine.storages = cache: Shrine :: Storage :: FileSystem.new ("public", prefix : "uploads / cache"), butik: Shrine :: Lagring :: FileSystem.new ("public", prefix: "uploads / store"),
Logger kommer helt enkelt att mata in några felsökningsinformation i konsolen för att du säger hur mycket tid som spenderades för att bearbeta en fil. Detta kan komma till nytta.
2015-10-09T20: 06: 06.676Z # 25602: STORE [cache] ImageUploader [: avatar] Användare [29543] 1 fil (0.1s) 2015-10-09T20: 06: 06.854Z # 25602: PROCESS [store]: ImageUploader [: avatar] Användare [29543] 1-3 filer (0.22s) 2015-10-09T20: 06: 07.133Z # 25602: DELETE [förstört]: ImageUploader [: avatar] Användare [29543] 3 filer (0.07s)
Alla uppladdade filer lagras inuti offentliga / uppladdningar katalogen. Jag vill inte spåra dessa filer i Git, så uteslut denna mapp:
offentliga / uppladdningar
Skapa nu en särskild "uppladdare" -klass som ska vara värd för modellspecifika inställningar. För tillfället kommer den här klassen att vara tom:
klass ImageUploader < Shrine end
Slutligen, inkludera denna klass inuti Foto
modell:
inkludera ImageUploader [: image]
[:bild]
lägger till ett virtuellt attribut som ska användas vid konstruktion av en blankett. Ovanstående rad kan skrivas om som:
inkludera ImageUploader.attachment (: bild) # eller inkludera ImageUploader :: Attachment.new (: image)
Trevlig! Nu är modellen utrustad med Shrine-funktionalitet, och vi kan gå vidare till nästa steg.
För den här demonstrationen behöver vi bara en kontroller för att hantera foton. De index
sidan kommer att fungera som root:
klass PhotosController < ApplicationController def index @photos = Photo.all end end
Vyn:
foton
<%= link_to 'Add Photo', new_photo_path %> <%= render @photos %>
För att göra @photos
array, en del är obligatorisk:
<% if photo.image_data? %> <%= image_tag photo.image_url %> <% end %><%= photo.title %> | <%= link_to 'Edit', edit_photo_path(photo) %>
image_data?
är en metod som presenteras av ActiveRecord som kontrollerar om en post har en bild.
bild URL
är en helgedomsmetod som helt enkelt återger en väg till originalbilden. Det är självklart mycket bättre att visa en liten miniatyr istället, men vi tar hand om det senare.
Lägg till alla nödvändiga vägar:
resurser: bilder, bara: [: ny,: skapa,: index,: redigera,: uppdatera] root 'foton # index'
Det här är det - grundarbetet är klart, och vi kan gå vidare till den intressanta delen!
I det här avsnittet visar jag hur du lägger till funktionaliteten för att faktiskt ladda upp filer. Kontrolleråtgärderna är väldigt enkla:
def new @photo = Photo.new end def skapa @photo = Photo.new (photo_params) om @ photo.save flash [: success] = 'Foto lagt till!' redirect_to photos_path else render "new" slutet
Den enda gotchaen är den för starka parametrar som du måste tillåta bild
virtuell attribut, inte den image_data
.
privat def photo_params params.require (: foto) .permit (: titel,: bild) slutet
Skapa ny
se:
Lägg till foto
<%= render 'form' %>
Formulärens partiella är också trivial:
<%= form_for @photo do |f| %> <%= render "shared/errors", object: @photo %> <%= f.label :title %> <%= f.text_field :title %> <%= f.label :image %> <%= f.file_field :image %> <%= f.submit %> <% end %>
Återigen, notera att vi använder bild
attribut, inte den image_data
.
Slutligen lägg till en annan partiell för att visa fel:
<% if object.errors.any? %>Följande fel hittades:
Det här är ganska mycket allt-du kan börja ladda upp bilder just nu.
Naturligtvis måste mycket mer arbete göras för att slutföra demo-appen. Det största problemet är att användarna kan ladda upp absolut vilken typ av fil som helst, vilket inte är särskilt bra. Lägg därför till ytterligare ett plugin för att stödja valideringar:
Shrine.plugin: validation_helpers
Ställ in valideringslogiken för ImageUploader
:
Attacher.validate validate_max_size 1.megabyte, meddelande: "är för stor (max är 1 MB)" validate_mime_type_inclusion ['image / jpg', 'image / jpeg', 'bild / png'] slut
Jag tillåter bara JPG och PNG bilder mindre än 1 MB att ladda upp. Tweak dessa regler som du tycker är lämplig.
En annan viktig sak att notera är att, som vanligt, ska Shrine bestämma en fils MIME-typ med HTTP-rubriken Content-Type. Den här rubriken skickas av webbläsaren och ställs endast ut baserat på filens tillägg, vilket inte alltid är önskvärt.
Om du vill bestämma MIME-typen baserat på filens innehåll, använd sedan ett plugin som heter determ_mime_type. Jag kommer att inkludera den inom uppladdarklassen, eftersom andra modeller kanske inte kräver denna funktion:
plugin: determine_mime_type
Detta plugin kommer som standard att använda Linux-filverktyget.
För närvarande, när en användare skickar en blankett med felaktiga uppgifter, visas formuläret igen med fel som gjorts ovan. Problemet är emellertid att den bifogade bilden kommer att gå vilse, och användaren måste välja den en gång till. Det här är väldigt enkelt att fixa med ännu ett annat plugin som heter cached_attachment_data:
plugin: cached_attachment_data
Lägg nu enkelt ett doldt fält i din formulär.
<%= f.hidden_field :image, value: @photo.cached_image_data %> <%= f.label :image %> <%= f.file_field :image %>
Nu kan bilder laddas upp, men det finns inget sätt att redigera dem, så låt oss fixa det direkt. Den motsvarande styrelsens åtgärder är något triviala:
def redigera @photo = Photo.find (params [: id]) slutdefinition @photo = Photo.find (params [: id]) om @ photo.update_attributes (photo_params) flash [: success] = 'Foto redigerade!' redirect_to photos_path else render redigera änden
Det samma _form
delvis kommer att utnyttjas:
Redigera Foto
<%= render 'form' %>
Trevligt men inte tillräckligt: Användare kan fortfarande inte ta bort en uppladdad bild. För att tillåta detta behöver vi-gissa vad-ett annat plugin:
plugin: remove_attachment
Det använder ett virtuellt attribut som heter : remove_image
, så tillåta det inom kontrollenheten:
def photo_params params.require (: photo) .permit (: title,: image,: remove_image) avsluta
Visa bara en kryssruta för att ta bort en bild om en post har en bilaga på plats:
<% if @photo.image_data? %> Ta bort bilagan: <%= f.check_box :remove_image %> <% end %>
För närvarande visar vi ursprungliga bilder, vilket inte är det bästa sättet att förhandsgranska: bilder kan vara stora och uppta för mycket utrymme. Självklart kan du helt enkelt använda CSS bredd
och höjd
attribut, men det är också en dålig idé. Du ser att även om bilden är liten för att använda format, behöver användaren fortfarande ladda ner originalfilen, vilket kan vara ganska stor.
Därför är det mycket bättre att generera en liten förhandsgranskningsbild på serverns sida under den första uppladdningen. Detta innebär två plugins och två extra pärlor. För det första släppa i pärlorna:
pärla "image_processing" pärla "mini_magick", "> = 4.3.5"
Image_processing är en speciell pärla skapad av författaren av Shrine. Den presenterar några metoder på hög nivå för att manipulera bilder. Denna pärla är beroende av mini_magick, en Ruby wrapper för ImageMagick. Som du har gissat behöver du ImageMagick på ditt system för att kunna köra den här demo.
Installera dessa nya pärlor:
buntinstallation
Nu innehåller plugins tillsammans med deras beroende:
kräva "image_processing / mini_magick" class ImageUploader < Shrine include ImageProcessing::MiniMagick plugin :processing plugin :versions # other code… end
Bearbetning är plugin som tillåter oss att manipulera en bild (till exempel krympa, rotera, konvertera till ett annat format, etc.). Versioner kan i sin tur ge oss en bild i olika varianter. För denna demo lagras två versioner: "original" och "tumme" (omformat till 300x300
).
Här är koden för att bearbeta en bild och lagra sina två versioner:
klass ImageUploader < Shrine process(:store) do |io, context| original: io, thumb: resize_to_limit!(io.download, 300, 300) end end
resize_to_limit!
är en metod som tillhandahålls av image_processing-pärlan. Den krymper bara en bild ner till 300x300
om det är större och gör ingenting om det är mindre. Dessutom håller den det ursprungliga bildförhållandet.
Nu när du visar bilden behöver du bara ge antingen :original
eller :tumme
argument till bild URL
metod:
<% if photo.image_data? %> <%= image_tag photo.image_url(:thumb) %> <% end %><%= photo.title %> | <%= link_to 'Edit', edit_photo_path(photo) %>
Samma sak kan göras inuti formuläret:
<% if @photo.image_data? %> <%= image_tag @photo.image_url(:thumb) %> Ta bort bilagan: <%= f.check_box :remove_image %> <% end %>
För att automatiskt radera de bearbetade filerna efter att uppladdning är klar kan du lägga till ett plugin som heter delete_raw:
plugin: delete_raw
Bortsett från att du faktiskt gör en bild kan du också hämta dess metadata. Låt oss till exempel visa originalfotoets storlek och MIME-typ:
<% if photo.image_data? %> <%= image_tag photo.image_url(:thumb) %>Storlek <%= photo.image[:original].size %> bitgrupper
<% end %>
MIME-typ <%= photo.image[:original].mime_type %>
<%= photo.title %> | <%= link_to 'Edit', edit_photo_path(photo) %>
Vad sägs om dess dimensioner? Tyvärr lagras de inte som standard, men det här är möjligt med ett plugin som heter store_dimensions.
Plugin store_dimensions beror på snabbbilden, så koppla upp den nu:
pärla "snabbbild"
Glöm inte att springa:
buntinstallation
Nu bara inkludera plugin:
plugin: store_dimensions
Och visa måtten med hjälp av bredd
och höjd
metoder:
<% if photo.image_data? %> <%= image_tag photo.image_url(:thumb) %>Storlek <%= photo.image[:original].size %> bitgrupper
<% end %>
MIME-typ <%= photo.image[:original].mime_type %>
Mått <%= "#photo.image[:original].widthx#photo.image[:original].height" %><%= photo.title %> | <%= link_to 'Edit', edit_photo_path(photo) %>
Det finns också en mått
tillgänglig metod som returnerar en array som innehåller bredd och höjd (till exempel, [500, 750]
).
Utvecklare väljer ofta molntjänster för att vara värd för uppladdade filer, och Shrine presenterar en sådan möjlighet. I det här avsnittet visar jag hur du laddar upp filer till Amazon S3.
Som det första steget, ta med två fler pärlor i Gemfile:
pärla "aws-sdk", "~> 2.1" -grupp: utveckling gör pärla "dotenv-rails" slutet
aws-sdk krävs för att arbeta med S3: s SDK, medan dotenv-skenor kommer att användas för att hantera miljövariabler i utveckling.
buntinstallation
Innan du fortsätter bör du få ett nyckelpar för åtkomst till S3 via API. För att få det, logga in (eller anmäl dig) till Amazon Web Services Console och navigera till Säkerhetsuppgifter> Användare. Skapa en användare med behörigheter för att manipulera filer på S3. Här är den enkla policyen som presenterar full tillgång till S3:
"Version": "2016-11-14", "Uttalande": ["Effekt": "Tillåt", "Åtgärd": "s3: *", "Resurs": "*"]
Ladda ner den skapade användarens nyckelpar. Alternativt kan du använda root accessnycklar, men jag avskräcka starkt du gör det eftersom det är mycket osäkert.
Skapa sedan en S3-hink som värd för dina filer och lägg till en fil i projektets rot för att vara värd för din konfiguration:
S3_KEY = YOUR_KEY S3_SECRET = YOUR_SECRET S3_BUCKET = YOUR_BUCKET S3_REGION = DIN_REGION
Utsätt aldrig någonsin den här filen till allmänheten, och se till att du utesluter den från Git:
.env
Ändra nu Shrine's globala konfiguration och introducera ett nytt lagringsutrymme:
kräver "shrine" kräver "shrine / storage / s3" s3_options = access_key_id: ENV ['S3_KEY'], secret_access_key: ENV ['S3_SECRET'], region: ENV ['S3_REGION'], hink: ENV ['S3_BUCKET'] , Shrine.storages = cache: Shrine :: Lagring :: FileSystem.new ("public", prefix: "uploads / cache"), butik: Shrine :: Lagring :: S3.new (prefix: "store" ** s3_options),
Det är allt! Inga ändringar måste göras till andra delar av appen, och du kan omedelbart testa det här nya lagret. Om du får fel från S3 relaterade till felaktiga nycklar, se till att du kopierat nyckeln och hemligheten noggrant, utan några efterföljande utrymmen och osynliga speciella symboler.
Vi har kommit till slutet av den här artikeln. Förhoppningsvis, nu känner du dig mycket säker på att använda helgedom och är angelägna om att använda den i ett av dina projekt. Vi har diskuterat många av denna pärls funktioner, men det finns ännu mer, som möjligheten att lagra ytterligare sammanhang tillsammans med filer och direkt uppladdningsmekanism.
Därför, bläddra i Shrine dokumentation och dess officiella hemsida, som grundligt beskriver alla tillgängliga plugins. Om du har andra frågor kvar om denna pärla, tveka inte att skicka in dem. Jag tackar dig för att du bodde hos mig, och vi ses snart!