Det er mange filopplasting edelstener der ute som CarrierWave, Paperclip og Dragonfly, for å nevne noen. De har alle sine spesifikasjoner, og sannsynligvis har du allerede brukt minst en av disse edelstenene.
I dag vil jeg imidlertid introdusere en relativt ny, men veldig kul løsning kalt Shrine, skapt av Janko Marohnić. I motsetning til noen andre lignende perler har den en modulær tilnærming, noe som betyr at hver funksjon er pakket som en modul (eller plugg inn i helligdomens terminologi). Vil du støtte valideringer? Legg til et plugin. Ønsker du å gjøre noen filbehandling? Legg til et plugin! Jeg elsker virkelig denne tilnærmingen, da det lar deg enkelt kontrollere hvilke funksjoner som vil være tilgjengelige for hvilken modell.
I denne artikkelen skal jeg vise deg hvordan du skal:
Kildekoden for denne artikkelen er tilgjengelig på GitHub.
Den fungerende demoen finner du her.
For å starte, opprett et nytt Rails-program uten standard testing suite:
skinner nye FileGuru -T
Jeg skal bruke Rails 5 for denne demonstrasjonen, men de fleste konseptene gjelder også versjoner 3 og 4.
Drop Shrine perlen i Gemfile din:
perle "helligdommen"
Kjør deretter:
bunt installasjon
Nå vil vi kreve en modell som jeg skal ringe Bilde
. Helligdom lagrer all filrelatert informasjon i en spesiell tekstkolonne som slutter med a _data
suffiks. Opprett og bruk tilsvarende migrering:
skinner g modell Foto tittel: streng image_data: tekstskinner db: migrere
Merk at for eldre versjoner av Rails, bør den sistnevnte kommandoen være:
rake db: migrere
Konfigurasjonsalternativer for helligdommen kan settes både globalt og per modell. Globale innstillinger er gjort, selvfølgelig, inne i initialiseringsfilen. Der skal jeg koble de nødvendige filene og plugins. Plugins brukes i Shrine for å trekke ut funksjonsstykker i separate moduler, noe som gir deg full kontroll over alle tilgjengelige funksjoner. For eksempel er det plugins for validering, bildebehandling, caching vedlegg og mer.
For nå, la oss legge til to plugins: en for å støtte ActiveRecord og en annen for å sette opp logging. De kommer til å bli inkludert globalt. Opprett også filsystemlagring:
krever "shrine" krever "shrine / storage / file_system" Shrine.plugin: activerecord Shrine.plugin: logging, logger: Rails.logger Shrine.storages = cache: Shrine :: Lagring :: FileSystem.new ("public", prefiks : "opplastinger / cache"), butikk: Shrine :: Lagring :: FileSystem.new ("public", prefix: "uploads / store"),
Logger vil ganske enkelt sende ut noen feilsøkingsinformasjon inne i konsollen for at du sier hvor mye tid det var brukt til å behandle en fil. Dette kan komme til nytte.
2015-10-09T20: 06: 06.676Z # 25602: BUTIKK [cache] ImageUploader [: avatar] Bruker [29543] 1 fil (0.1s) 2015-10-09T20: 06: 06.854Z # 25602: PROCESS [butikk]: ImageUploader [: avatar] Bruker [29543] 1-3 filer (0.22s) 2015-10-09T20: 06: 07.133Z # 25602: SLETT [ødelagt]: ImageUploader [: avatar] Bruker [29543] 3 filer (0.07s)
Alle opplastede filer lagres inne i offentlige / opplastinger katalogen. Jeg vil ikke spore disse filene i Git, så unngår denne mappen:
offentlige / opplastinger
Opprett nå en spesiell "opplastings" -klasse som skal være vert for modellspesifikke innstillinger. For nå vil denne klassen være tom:
klasse ImageUploader < Shrine end
Til slutt, inkludere denne klassen inne i Bilde
modell:
inkludere ImageUploader [: image]
[:bilde]
legger til et virtuelt attributt som skal brukes når du bygger et skjema. Ovenstående linje kan skrives om som:
Inkluder ImageUploader.attachment (: image) # eller inkluder ImageUploader :: Attachment.new (: image)
Hyggelig! Nå er modellen utstyrt med Shrine-funksjonalitet, og vi kan fortsette til neste trinn.
For denne demonstrasjons formål trenger vi bare én kontroller for å administrere bilder. De index
siden vil fungere som roten:
klasse PhotosController < ApplicationController def index @photos = Photo.all end end
Utsikten:
Bilder
<%= link_to 'Add Photo', new_photo_path %> <%= render @photos %>
For å gjengi @photos
array, en del er nødvendig:
<% if photo.image_data? %> <%= image_tag photo.image_url %> <% end %><%= photo.title %> | <%= link_to 'Edit', edit_photo_path(photo) %>
image_data?
er en metode presentert av ActiveRecord som kontrollerer om en plate har et bilde.
image_url
er en Shrine-metode som bare returnerer en bane til det opprinnelige bildet. Selvfølgelig er det mye bedre å vise et lite miniatyrbilde i stedet, men vi vil ta vare på det senere.
Legg til alle nødvendige ruter:
ressurser: bilder, bare: [: ny,: lag,: indeks,: rediger,: oppdater] rot 'bilder # indeks'
Dette er det-grunnlaget er gjort, og vi kan fortsette til den interessante delen!
I denne delen vil jeg vise deg hvordan du legger til funksjonaliteten for å faktisk laste opp filer. Kontrolleren handlinger er veldig enkle:
def new @photo = Photo.new end def opprette @photo = Photo.new (photo_params) hvis @ photo.save flash [: success] = 'Bilde lagt!' redirect_to photos_path annet gjengi 'ny' sluttend
Den eneste gotchaen er at for sterke parametere må du tillate bilde
virtuell attributt, ikke den image_data
.
privat def photo_params params.require (: foto) .permit (: title,: image) end
Opprett ny
utsikt:
Legg til bildet
<%= render 'form' %>
Skjemaets del er også trivielt:
<%= 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 %>
Igjen, merk at vi bruker bilde
attributt, ikke den image_data
.
Til slutt, legg til en annen delvis for å vise feil:
<% if object.errors.any? %>Følgende feil ble funnet:
Dette er stort sett alt-du kan begynne å laste opp bilder akkurat nå.
Selvfølgelig må mye mer arbeid gjøres for å fullføre demo-appen. Hovedproblemet er at brukerne kan laste opp absolutt alle typer filer med hvilken som helst størrelse, noe som ikke er spesielt bra. Legg derfor til et annet plugin for å støtte valideringer:
Shrine.plugin: validation_helpers
Sett inn valideringslogikken for ImageUploader
:
Attacher.validate validate_max_size 1.megabyte, melding: "er for stor (maks er 1 MB)" validate_mime_type_inclusion ['image / jpg', 'image / jpeg', 'image / png'] slutten
Jeg tillater bare JPG og PNG-bilder mindre enn 1 MB å bli lastet opp. Tweak disse reglene som du ser hensiktsmessig.
En annen viktig ting å merke seg er at Shrine vil som standard bestemme en fils MIME-type ved hjelp av HTTP-overskriften Content-Type. Denne overskriften overføres av nettleseren og settes bare ut fra filens utvidelse, noe som ikke alltid er ønskelig.
Hvis du ønsker å bestemme MIME-typen basert på filens innhold, bruker du et plugin som kalles determine_mime_type. Jeg vil inkludere den i opplasterklassen, da andre modeller kanskje ikke krever denne funksjonaliteten:
plugin: determine_mime_type
Dette pluginet kommer til å bruke Linuxs filverktøy som standard.
Foreløpig, når en bruker sender et skjema med feil data, vil skjemaet vises igjen med feil gjengitt ovenfor. Problemet er imidlertid at det vedlagte bildet vil gå tapt, og brukeren må velge den igjen. Dette er veldig enkelt å fikse ved hjelp av enda et plugin som heter cached_attachment_data:
plugin: cached_attachment_data
Legg nå bare et skjult felt inn i skjemaet ditt.
<%= f.hidden_field :image, value: @photo.cached_image_data %> <%= f.label :image %> <%= f.file_field :image %>
Nå kan bilder lastes opp, men det er ingen måte å redigere dem, så la oss fikse det med en gang. Tilsvarende kontrollørens handlinger er noe trivielle:
def edit @photo = Photo.find (params [: id]) slutten def update @photo = Photo.find (params [: id]) hvis @ photo.update_attributes (photo_params) flash [: success] = 'Foto redigert!' redirect_to photos_path ellers gi endring endend
Det samme _form
delvis vil bli utnyttet:
Rediger bilde
<%= render 'form' %>
Fint, men ikke nok: Brukerne kan fortsatt ikke fjerne et opplastet bilde. For å tillate dette må vi gjette hva-et annet program:
plugin: remove_attachment
Den bruker et virtuelt attributt som heter : remove_image
, så tillat det inne i kontrolleren:
def photo_params params.require (: photo) .permit (: title,: image,: remove_image) avslutte
Vis bare en avkrysningsboks for å fjerne et bilde hvis en plate har et vedlegg på plass:
<% if @photo.image_data? %> Fjern vedlegg: <%= f.check_box :remove_image %> <% end %>
For øyeblikket viser vi originale bilder, som ikke er den beste tilnærmingen for forhåndsvisninger: bildene kan være store og oppta for mye plass. Selvfølgelig kan du bare ansette CSS bredde
og høyde
attributter, men det er også en dårlig ide. Du ser, selv om bildet er satt til å være lite ved hjelp av stiler, må brukeren fortsatt laste ned den opprinnelige filen, noe som kan være ganske stor.
Derfor er det mye bedre å generere et lite forhåndsvisningsbilde på server siden under den første opplastingen. Dette innebærer to plugins og to ekstra edelstener. For det første, slipp i edelstenene:
perle "image_processing" perle "mini_magick", "> = 4.3.5"
Image_processing er en spesiell perle laget av forfatteren av Shrine. Den presenterer noen hjelpemetoder på høyt nivå for å manipulere bilder. Denne perlen er igjen avhengig av mini_magick, en Ruby wrapper for ImageMagick. Som du har gjettet, trenger du ImageMagick på systemet ditt for å kunne kjøre denne demoen.
Installer disse nye edelstenene:
bunt installasjon
Nå inkluderer pluginene sammen med deres avhengigheter:
krever "image_processing / mini_magick" klasse ImageUploader < Shrine include ImageProcessing::MiniMagick plugin :processing plugin :versions # other code… end
Behandling er pluginet som lar oss manipulere et bilde (for eksempel krympe det, rotere, konvertere til et annet format, etc.). Versjoner tillater oss å få et bilde i forskjellige varianter. For denne demoen blir to versjoner lagret: "original" og "tommel" (resized to 300x300
).
Her er koden for å behandle et bilde og lagre sine to versjoner:
klasse ImageUploader < Shrine process(:store) do |io, context| original: io, thumb: resize_to_limit!(io.download, 300, 300) end end
resize_to_limit!
er en metode som leveres av image_processing-perlen. Det krymper bare et bilde ned til 300x300
hvis det er større og gjør ingenting hvis det er mindre. Videre holder den det opprinnelige aspektforholdet.
Nå når du viser bildet, trenger du bare å gi enten :opprinnelig
eller :tommel
argument til image_url
metode:
<% if photo.image_data? %> <%= image_tag photo.image_url(:thumb) %> <% end %><%= photo.title %> | <%= link_to 'Edit', edit_photo_path(photo) %>
Det samme kan gjøres inne i skjemaet:
<% if @photo.image_data? %> <%= image_tag @photo.image_url(:thumb) %> Fjern vedlegg: <%= f.check_box :remove_image %> <% end %>
Hvis du vil slette de behandlede filene automatisk etter at opplastingen er fullført, kan du legge til et plugin som heter delete_raw:
plugin: delete_raw
Bortsett fra at du faktisk gir et bilde, kan du også hente metadataene sine. La oss for eksempel vise originalfotoets størrelse og MIME-type:
<% if photo.image_data? %> <%= image_tag photo.image_url(:thumb) %>Størrelse <%= photo.image[:original].size %> byte
<% end %>
MIME type <%= photo.image[:original].mime_type %>
<%= photo.title %> | <%= link_to 'Edit', edit_photo_path(photo) %>
Hva med dimensjonene? Dessverre lagres de ikke som standard, men dette er mulig med et plugin som heter store_dimensions.
Store_dimensions-pluginet er avhengig av hurtigbildet, så koble det opp nå:
perle 'fastimage'
Ikke glem å kjøre:
bunt installasjon
Nå bare inkludere plugin:
plugin: store_dimensions
Og vis dimensjonene ved hjelp av bredde
og høyde
metoder:
<% if photo.image_data? %> <%= image_tag photo.image_url(:thumb) %>Størrelse <%= photo.image[:original].size %> byte
<% end %>
MIME type <%= photo.image[:original].mime_type %>
dimensjoner <%= "#photo.image[:original].widthx#photo.image[:original].height" %><%= photo.title %> | <%= link_to 'Edit', edit_photo_path(photo) %>
Det er også en dimensjoner
metode tilgjengelig som returnerer en matrise som inneholder bredde og høyde (for eksempel, [500, 750]
).
Utviklere velger ofte skygtjenester for å være vert for opplastede filer, og Shrine presenterer en slik mulighet. I denne delen vil jeg vise deg hvordan du laster opp filer til Amazon S3.
Som det første trinnet, ta med to flere edelstener inn i Gemfile:
perle "aws-sdk", "~> 2.1" -gruppe: utvikling gjør perlen 'dotenv-skinner' ende
aws-sdk er pålagt å jobbe med S3s SDK, mens dotenv-skinner vil bli brukt til å håndtere miljøvariabler i utvikling.
bunt installasjon
Før du fortsetter, bør du skaffe et nøkkelpar for å få tilgang til S3 via API. For å få det, logg på (eller registrer deg) til Amazon Web Services Console og naviger til Sikkerhetserklæringer> Brukere. Opprett en bruker med tillatelser til å manipulere filer på S3. Her er den enkle politikken som gir full tilgang til S3:
"Version": "2016-11-14", "Statement": ["Effect": "Tillat", "Action": "s3: *", "Ressurs": "*"]
Last ned den opprettede brukerens nøkkelpar. Alternativt kan du bruke root-tilgangsnøkler, men jeg motvirke sterkt du fra å gjøre det som det er veldig usikkert.
Deretter lager du en S3-bøtte for å være vert for filene dine og legge til en fil i prosjektets rot for å være vert for konfigurasjonen din:
S3_KEY = YOUR_KEY S3_SECRET = YOUR_SECRET S3_BUCKET = YOUR_BUCKET S3_REGION = YOUR_REGION
Aldri utsette deg denne filen til offentligheten, og sørg for at du ekskluderer den fra Git:
.env
Endre nå Shrine's global konfigurasjon og innfør et nytt lagringsområde:
krever "shrine" krever "shrine / storage / s3" s3_options = access_key_id: ENV ['S3_KEY'], secret_access_key: ENV ['S3_SECRET'], region: ENV ['S3_REGION'], bøtte: ENV ['S3_BUCKET'] , Shrine.storages = cache: Shrine :: Lager :: FileSystem.new ("public", prefix: "opplastinger / cache"), butikk: Shrine :: Storage :: S3.new (prefix: "store" ** s3_options),
Det er det! Ingen endringer må gjøres til de andre delene av appen, og du kan teste dette nye lagringsmediet med en gang. Hvis du mottar feil fra S3 relatert til feil knapper, må du sørge for at du nøyaktig kopierte nøkkelen og hemmelig, uten noen etterfølgende mellomrom og usynlige spesielle symboler.
Vi har kommet til slutten av denne artikkelen. Forhåpentligvis føler du deg mye trygg på å bruke helligdommen og er ivrig etter å ansette den i en av prosjektene dine. Vi har diskutert mange av denne perlefunksjonene, men det er enda mer, som evnen til å lagre tilleggskontekst sammen med filer og direkte opplastingsmekanisme.
Derfor, bla gjennom Shrine dokumentasjon og dets offisielle nettside, som grundig beskriver alle tilgjengelige plugins. Hvis du har andre spørsmål igjen om denne perlen, ikke nøl med å legge inn dem. Jeg takker for at du bodde hos meg, og jeg ser deg snart!