Tag: paperclip

Rails + przechowywanie wielu obrazów (miniaturek, avatarów, zdjęć) w systemie

Przeglądając devpytania natknąłem się na pytanie dotyczące przechowywania zdjęć użytkowników w serwisie - biorąc pod uwagę ilości "hurtowe" (link).

Nie miałem potrzeby aby wdrażać takie rozwiązanie, ponieważ nie pisałem nigdy części systemu, która miałaby przechowywać ponad 32k plików (chociaż ostatnio się to zmieniło ;) ). Wychodząc naprzeciw wyzwaniu, postanowiłem dodać taką opcję i jak to bywa w wypadku Railsów - nie zajęło mi to zbyt wiele czasu.

Rozwiązanie znalazłem tutaj. Jest ono proste jak konstrukcja cepa a jego wdrożenie nie zajmuje zbyt wiele czasu.

W katalogu config/initializers tworzymy sobie plik, np o nazwie: paperclip_extensions.rb czy tam czymś podobnym, po czym wstawiamy do tego pliku taki oto kod:

Paperclip.interpolates :hashed_path do |attachment, style|
  hash = Digest::MD5.hexdigest(attachment.instance.id.to_s + 'cos_tam_tajnego')
  hash_path = ''
  3.times { hash_path += '/' + hash.slice!(0..2) }
  hash_path[1..12]
end

Mimo że pierwotny autor na blogu uważa że cos_tam_tajnego nie jest istotne, ja pozwolę się z nim nie zgodzić ;)

Dodanie soli do tego hasha, sprawia że ktoś kto chciałby "zassać" nasze zdjęcia, przy pomocy jakiegoś kodu automatycznego, będzie miał utrudnione zadanie.

Nie dając soli, potencjalny "złodziej" bardzo szybko zauważy prawidłowość pt: MD5(id) i podział na 3 części. Stosując tutaj sól oraz moje rozwiązanie z tego wątku - zabezpieczamy się w dużym stopniu przed tego typu zagrywkami.

Po dodaniu tego rozszerzenia do Paperclipa, otrzymujemy nowe słowo "klucz" do wykorzystania z tym pluginem. Jest to :hashed_path który możemy wykorzystać tak samo jak np: :id_:style.:extension, tworząc przykładowo taką oto ścieżkę:

:url => "/pictures/:hashed_path/:id/:id_:style.:extension"

:hashed_path zostanie zamieniony na strukturę katalogów w stylu /ghw/jre/fhw. Dzięki temu w jednym katalogu nie będzie przechowywana zbyt duża liczba plików co mogłoby się skończyć problemami z systemem plików.

Według mnie implementacja tego kodu jest na tyle prosta i szybka, że warto ją włączać nawet w projekty które nie mają w założeniach być "super obciążone", ponieważ jak to w internecie bywa - wszyscy wiemy ;)

Paperclip – przycinanie obrazków – parametry

Oto jak sprawdzają się poszczególne parametry przy przycinaniu obrazków.
Obraz bazowy (512x346px):

viva_wallpaper

Bez przekształcenia (tylko zmiana rozmiaru) 150x150 powoduje zmianę rozmiaru obrazka do podanych wartości, z zachowaniem proporcji boków czyli otrzymamy obraz o rozmiarze 150x101.

493076142_mini

Najprostsze przekształcenie, czyli 150x150> sprawi, że nasz obraz będzie miał wymiary 150x101 pikseli. Jeśli plik byłby mniejszy, to nic się w nim nie zmieni. Jednak jeśli był większy, to zostanie przeskalowany do "pełniejszego" boku, z zachowaniem stosunku długości boków.

493076142_mini

Opcja 150x150! powoduje że obraz zostanie rozciągnięty do podanych wymiarów. Jeśli któryś bok jest dłuższy niż podane, to zostanie on zwężony. Jednym słowem, obraz będzie ściśnięty bądź rozciągnięty do podanego rozmiaru:

493076142_mini

Następną możliwością jest 150x150# która najpierw tak zmniejsza rozmiar obrazka, aby nie stracił proporcji, a następnie wszystko co "wystaje" poza podany rozmiar zostaje odrzucone.

493076142_mini

50% - zmniejsza nasz obraz z zachowaniem proporcji, do 50% oryginału (tutaj można jeszcze skalować bokami czyli: 20%x50% wtedy szerokość będzie mniejsza o 20% zaś wysokość o 50%):

mini_thumb_493076142

211 - automatycznie zmniejsza obraz aby miał szerokość 211px - wysokość dobierana automatycznie:

mini_thumb_493076142

x123 - zmniejszy obraz do podanej wysokości, dobierając szerokość tak aby proporcje zostały zachowane:

mini_thumb_493076142

200x200^ - dopasowuje obraz z zachowaniem proporcji - tylko wtedy jeśli jest mniejszy niż podane wymiary. Nasz jest większy więc po prostu go nie przeskaluje.

22500@ - dopasowuje obraz do podanej ilości pikseli, z zachowaniem proporcji:

mini_thumb_493076142

Copyright © 2025 Closer to Code

Theme by Anders NorenUp ↑