Změna velikosti obrázku za běhu

Téměř v každé webové aplikaci, která používá obrázky, je potřeba vytvořit malé kopie těchto obrázků a často existuje několik formátů pro další obrázky.
Přidávání nových dimenzí do existující aplikace také způsobuje určité bolesti hlavy. Proto úkol:

Úkol

Označme seznam požadavků:

  • Vytvářejte další obrázky libovolného formátu za chodu bez zavádění dalších funkcí do aplikace kdykoli během existence aplikace;
  • Další obrázky není nutné generovat na každý požadavek;
  • Zakažte možnost generování dalších obrázků neurčených formátů.

Vysvětlím poslední bod, protože je mírně v rozporu s prvním bodem. Pokud otevřeme generování libovolných obrázků, pak existuje možnost útoku na web generováním velkého množství požadavků na změnu velikosti obrázku do nekonečného množství formátů, takže je potřeba tuto zranitelnost uzavřít.

konfigurace instalace nginx

K vyřešení výše uvedených požadavků potřebujeme následující sadu modulů nginx:

Moduly ngx_http_image_filter_module и ngx_http_secure_link_module nejsou ve výchozím nastavení nainstalovány, takže musí být specifikovány ve fázi konfigurace instalace Nginx:

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

konfigurace nginx

Do naší konfigurace hostitele přidáme nový umístění a obecné parametry mezipaměti:

...
    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;
        }
...
    }
...

Do konfigurace také přidáme nového hostitele:

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; }
}

V důsledku toho lze získat další obrázky pomocí následujících odkazů:

* try_files — citlivý na mezery a ruské znaky, takže jsem si musel udělat berličku přezdívka.

Použití ve webové aplikaci

Na úrovni webové aplikace můžete provést následující postup (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'
                );

I když bych také doporučil spočítat velikosti náhled.

Hrábě

Při mazání původního obrázku se náhledy přirozeně nevymažou z mezipaměti, dokud není mezipaměť zneplatněna, a v našem případě mohou náhledy existovat i den po smazání, ale to je maximální doba.

originál

Zdroj: www.habr.com

Přidat komentář