Resize av bilder on-the-fly

I nästan alla webbapplikationer som använder bilder finns det ett behov av att skapa miniatyrbilder av dessa bilder, ofta i flera olika format.
Att lägga till nya storlekar i en befintlig applikation kan också orsaka en del huvudvärk. Därför är uppgiften:

Uppgift

Vi anger en lista med krav:

  • Skapa ytterligare bilder i valfria format i realtid utan att lägga till extra funktionalitet i applikationen när som helst under applikationens livscykel;
  • Ytterligare bilder ska inte skapas vid varje begäran;
  • Stäng möjligheten att skapa ytterligare bilder i oetablerade format.

Jag förklarar den sista punkten, eftersom den är något motsägelsefull mot den första punkten. Om vi gör det möjligt att skapa valfria bilder finns det en risk för attacker på webbplatsen genom att skapa ett stort antal begärningar för att ändra storlek på bilden i oändliga format, så denna sårbarhet måste stängas.

Nginx-installationskonfiguration

För att uppfylla ovanstående krav behöver vi följande uppsättning Nginx-moduler:

Moduler ngx_http_image_filter_module och ngx_http_secure_link_module de installeras inte som standard, så de måste anges vid installationskonfigurationen nginx:

phoinix@phoinix-work:~\/src\/nginx-0.8.29
$ .\/configure --with-http_secure_link_module --with-http_image_filter_module

Nginx-konfiguration

Vi lägger till en ny plats och de allmänna cacheparametrarna:

...
    proxy_cache_path /www/myprojects/cache levels=1:2 keys_zone=image-preview:10m;
...
    server {
...
        location ~ ^/preview/([cir])/(.+) {
        # Тип операции
            set $oper $1;
        # Параметры изображения и путь к файлу
            set $remn $2;
        # Проксируем на отдельный хост
            proxy_pass http://myproject.ru:81/$oper/$remn;
            proxy_intercept_errors on;
            error_page 404 = /preview/404;
        # Кеширование
            proxy_cache image-preview;
            proxy_cache_key "$host$document_uri";
        # 200 ответы кешируем на 1 день
            proxy_cache_valid 200 1d;
        # остальные ответы кешируем на 1 минуту
            proxy_cache_valid any 1m;
        }
        
        # Возвращаем ошибку
        location = /preview/404 {
            internal;
            default_type image/gif;
            alias /www/myprojects/image/noimage.gif;
        }
...
    }
...

Vi lägger också till en ny värd i konfigurationen:

server {
    server_name                     myproject.ru;
    listen                          81;

    access_log                      /www/myproject.ru/logs/nginx.preview.access_log;
    error_log                       /www/myproject.ru/logs/nginx.preview.error_log info;

    # Указываем секретное слово для md5
    secure_link_secret              secret;

    # Ошибки отправляем она отдельный location
    error_page                      403 404 415 500 502 503 504 = @404;

    # location Для фильтра size
    location ~ ^/i/[^/]+/(.+) {
        
        # грязный хак от Игоря Сысоева *
        alias                       /www/myproject.ru/images/$1;
        try_files                   "" @404;
    
        # Проверяем правильность ссылки и md5
        if ($secure_link = "") { return 404; }
        
        # Используем соответсвующий фильтр
        image_filter                size;
    }

    # По аналогии остальные location для других фильтров
    location ~ ^/c/[^/]+/(d+|-)x(d+|-)\/(.+) {
        set                         $width  $1;
        set                         $height $2;
        
        alias                       /www/myproject.ru/images/$3;
        try_files                   "" @404;
    
        if ($secure_link = "") { return 404; }
    
        image_filter                crop  $width  $height;
    }
    
    location ~ ^/r/[^/]+/(d+|-)x(d+|-)\/(.+) {
        set                         $width  $1;
        set                         $height $2;

        alias                       /www/myproject.ru/images/$3;
        try_files                   "" @404;

        if ($secure_link = "") { return 404; }

        image_filter                resize  $width  $height;
    }

    location @404 { return 404; }
}

Som ett resultat kan ytterligare bilder hämtas via länkar:

* try_files — känslig för mellanslag och ryska tecken, så jag var tvungen att göra ett hack med alias.

Användning i webbapplikationen

På nivån av webbapplikationen kan följande procedur göras (Perl):

sub proxy_image {
    use Digest::MD5 qw /md5_hex/;
    my %params = @_;
    my $filter = {
                    size => 'i',
                    resize => 'r',
                    crop => 'c'            
                  }-> {$params{filter}} || 'r';
    my $path = ($filter ne 'i' ?
                    ( $params{height} || '_' ) . 'x' . ( $params{width} || '_' ) . ' /' :
                    ()
               ) . $params{source};
    my $md5 = md5_hex( $path . 'secret' );
    $path = '/preview/' . $filter . '/' . $md5 . '/' . $path;
    return $path;
}

my $preview_path = &proxy_image(
                    source => 'image1.jpg',
                    height => 100,
                    width => 100,
                    filter => 'resize'
                );

Även om jag skulle rekommendera att beräkna storlekarna preview.

Räfsor

När den ursprungliga bilden tas bort, kommer förhandsvisningen naturligtvis att raderas från cachen men kommer inte att göras förrän cachen ogiltigförklaras, och i vårt fall kan förhandsvisningarna existera i upp till ett dygn efter borttagning, men det är max tiden.

original

Källa: habr.com

Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar 🔥 Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster