Afbeeldingen on-the-fly resizen met Nginx en LuaJIT (OpenResty)

Al geruime tijd, geïnspireerd door een artikel Afbeeldingen on-the-fly resizen was er een configuratie voor het wijzigen van de grootte van afbeeldingen met behulp van ngx_http_image_filter_module en alles werkte zoals het hoorde. Maar er ontstond een probleem toen de manager afbeeldingen met exacte afmetingen nodig had voor upload naar bepaalde services, omdat dat hun technische vereisten waren. Bijvoorbeeld, als we een origineel van een afbeelding hebben met een grootte van 1200×1200, en bij het wijzigen van de grootte schrijven we iets als ?resize=600×400, dan krijgen we een proportioneel verkleinde afbeelding langs de kleinste rand, met een grootte van 400×400. Het is ook onmogelijk om een afbeelding met een hogere resolutie te verkrijgen (upscale). Dat wil zeggen, ?resize=1500×1500 zal dezelfde afbeelding retourneren 1200×1200

Een artikel kwam te hulp OpenResty: transformeer NGINX in een volledige applicatieserver om te begrijpen hoe Nginx met Lua werkt en de bibliotheek voor Lua isage/lua-imagick — Lua pure-c bindings naar ImageMagick. Waarom is deze oplossing gekozen en niet bijvoorbeeld iets in Python — omdat het snel en handig is. Je hoeft zelfs geen bestanden aan te maken, alles kan rechtstreeks in de Nginx-configuratie (niet verplicht).

Dus, wat hebben we nodig

Voorbeelden worden gegeven op basis van Debian.

Installatie van nginx en nginx-extras

apt-get update
apt-get install nginx-extras

Installatie van LuaJIT

apt-get -y install lua5.1 luajit-5.1 libluajit-5.1-dev

Installatie van imagemagick

apt-get -y install imagemagick

en bibliotheek magickwand voor, in mijn geval voor versie 6

apt-cache search libmagickwand
apt-get -y install libmagickwand-6.q16-3 libmagickwand-6.q16-dev

Bouwen van lua-imagick

Clone de repository (of haal de zip op en pak uit)

cd ~
git clone https://github.com/isage/lua-imagick.git
cd lua-imagick
mkdir build
cd build
cmake ..
make
make install

Als alles succesvol is verlopen, kan Nginx worden geconfigureerd.

Ik geef een voorbeeld van de config van de backend host, die zich bezighoudt met het wijzigen van de grootte. Deze wordt geproxied door de frontendserver met Nginx, waarop caching plaatsvindt voor een bepaalde tijd (een dag) en andere zaken.

nginx backend config

# Backend image server
server {
    listen       8082;
    listen [::]:8082;
    set $files_root /var/www/example.lh/frontend/web;
    root $files_root;
    access_log off;
    expires 1d;

    location /files {
        # дефолтные значения ресайза
        set $w 700;
        set $h 700;
        set $q 89;

        #1-89 allowed
        if ($arg_q ~ "^([1-9]|[1-8][0-9])$") {
            set $q $arg_q;
        }

        if ($arg_resize ~ "([d-]+)x([d+!^]+)") {  
            set $w $1;
            set $h $2;
            rewrite  ^(.*)$   /resize/$w/$h/$q$uri     last;
        }

        rewrite  ^(.*)$   /resize/$w/$h/$q$uri     last;
    }

    location ~* ^/resize/([d]+)/([d+!^]+)/([d]+)/files/(.+)$ {
        default_type 'text/plain';

        set $w $1;
        set $h $2;
        set $q $3;
        set $fname $4;

        # Есть возможность вынести весь Lua код в отдельный файл
        # content_by_lua_file /var/www/some.lua;
        # lua_code_cache off; #dev
        content_by_lua '
        local magick = require "imagick"
        local img = magick.open(ngx.var.files_root .. "/files/" .. ngx.var.fname)
        if not img then ngx.exit(ngx.HTTP_NOT_FOUND) end
        img:set_gravity(magick.gravity["CenterGravity"])

        if string.match(ngx.var.h, "%d+%+") then
            local h = string.gsub(ngx.var.h, "(%+)", "")
            resize = ngx.var.w .. "x" .. h
            -- для png с альфа каналом
            img:set_bg_color(img:has_alphachannel() and "none" or img:get_bg_color())
            img:smart_resize(resize)
            img:extent(ngx.var.w, h)
        else
                img:smart_resize(ngx.var.w .. "x" .. ngx.var.h)
        end

        if ngx.var.arg_q then img:set_quality(ngx.var.q) end

        ngx.say(img:blob())
        ';
    }
}

# Upstream
upstream imageserver {
    server localhost:8082;
}

server {
    listen 80;
    server_name examaple.lh;

    # отправляем все jpg и png картинки на imageserver
    location ~* ^/files/.+.(jpg|png) {
        proxy_buffers 8 2m;
        proxy_buffer_size 10m;
        proxy_busy_buffers_size 10m;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass     http://imageserver;  # Backend image server
    }
}

Wat nodig was (uitbreiding van de afbeelding aan de randen) gebeurt met behulp van img:extent() en wordt bepaald door de parameter resize met een teken + aan het einde.

De volgende parameters zijn beschikbaar:

  • WxH (Behoud de aspectverhouding, gebruik de grotere dimensie)
  • WxH^ (Behoud de aspectverhouding, gebruik de kleinere dimensie (crop))
  • WxH! (Negeer de aspectverhouding)
  • WxH+ (Behoud de aspectverhouding, voeg zijkanten toe)

Een samenvattende tabel met de resultaten van het wijzigen van de grootte

De uri parameter van de aanvraag
De grootte van de uitvoerafbeelding

?resize=400×200
200×200

?resize=400×200^
400×400

?resize=400×200!
400×200 (Niet proportioneel)

?resize=400×200+
400×200 (Proportioneel)

Afbeeldingen on-the-fly resizen met Nginx en LuaJIT (OpenResty)

Conclusie

Gezien de kracht en eenvoud van deze aanpak, kunnen dingen met behoorlijk complexe logica worden geïmplementeerd, zoals het toevoegen van watermerken of het realiseren van autorisatie met beperkte toegang. Om de mogelijkheden van de API voor het werken met afbeeldingen te ontdekken, kan men de documentatie van de bibliotheek raadplegen. isage/lua-imagick

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster