Dinamiškas thumbnail ‘o generavimas

Vakar vienam iš vystomų projektų reikėjo sukurti foto galerijos funkcionalumą. Nieko ypatingo: tiesiog “thumbnail’ai”, kuriuos paspaudus iššoka naujas langas su originalaus dydžio nuotrauka. Kiek panaršius internete sukūriau testinį variantą, kuris rašė dvi bylas: originalą bei thumbnail’ą, tačiau kiek pamąsčius nusprendžiau, jog to paties paveikslo (nors ir skirtingo dydžio) saugojimas bei juo manipuliavimas neatitinka DRY principų =) Tad beliko tik parašyti kodą, kuris dinamiškai formuotu thumbnailą.

Veikimo principas: žemiau pateiktas kodas keliauja į application.rb, ir išbandyti jį galima taip: [jūsų controllerio pavadinimas] / img?src=rails.png

Update: dado1945 prašymu pateikiu sprendimą su thumbnail’ų kešavimų =) (Daugiau apie http kešavimą)
Update2: ištaisiau tikrai kvailą klaidą kai paveiksliukas nekeitė dydžio dėl vienodų matmenų =)
Update3: Rimanto dėka calc_size funkcijos kodas tapo daug gražesnis. Ačiū.
Tikiuosi kažkam padės sutaupyti laiko =)
[ruby]
BASE_SIZE = 200.0

def calc_size(width, height)
ratio = [width, height].max / BASE_SIZE
[width, height].map { |s| s.div ratio }
end

def img
require ‘RMagick’

file = “public/images/#{params[:src]}”
if file and File.exists?(file)

req_last_modified = Time.rfc2822(@request.env[“HTTP_IF_MODIFIED_SINCE”]) rescue nil
last_modified = File.mtime(file)

@response.headers[‘Last-Modified’] = last_modified.rfc2822
if req_last_modified and last_modified < = req_last_modified render_text '', '304 Not Modified' else image = Magick::Image.read(file)[0] width, height = calc_size(image.columns, image.rows) image.resize!(width, height) send_data(image.to_blob, :disposition => ‘inline’, :type => image.mime_type, :filename => file)
end
else
render_text “Image not found!”
end
end
[/ruby]

11 Replies to “Dinamiškas thumbnail ‘o generavimas”

  1. Šaunuolis 🙂 Informacijos saugojimo prasme DRY principo nepažeidei, o pažeidei jį generuodamas tą pačią informaciją kiekvieną kartą kai jos reikia. Vat jeigu cache’intum sugeneruotus thumbnail’us tai jau būtų pilnas sprendimas…

  2. Hm, jai įdemiai peržiureti kodą, galima pamatyti kad yra išnaudojamas kešavimas vartotojo puseje – kas parodo, kad serverije gal but nera itin daug vietos, todėl buvo nuspresta išnaudoti processoriaus resursus.

    Nors, asmeniškai bučiau linkes į sugeneruotu paveiksliuku kešavima ir mažu peržiuru generavima įkraunant paveiksliuką, bet bendrai, priklauso nuo projekto lankomumo ir serverio apkrovimo.

  3. Pasirinkta paprastumo taktika: su nuotraukomis yra daromos skirtingos manipuliacijos ir daug papraščiau yra tvarkyti vieną bylą ir skirtingai ją atvaizduoti nei originalą ir thumbnailą.

  4. o jei nuotraukų yra 100k? ir vienu metu browsinančių vartotojų koks 1k? 🙂 ar ne per didelis overloadas hardwarui?

  5. Gaila, kad tuose “Getting real (scale later)” niekada nerašo, apie tai kad reikia vis del to 10 kartu apmastyti prieš ką nors darant.

  6. mano variantas:

    BASE_SIZE = 200.0
    def calc_size(width, height)
    ratio = [width, height].max / BASE_SIZE
    [width, height].map { |s| s.div ratio }
    end

  7. Rimantas, kol kas visa gyvenimo ir darbo praktika rodo, kad tam tikra dalis “kureju/developeriu” kaip tik vadovaujasi visishkai kitokia logika.

Leave a Reply

Your email address will not be published. Required fields are marked *