Redimensione imagens instantaneamente

Em quase todas as aplicações web que utilizam imagens, é necessário criar pequenas cópias dessas imagens e, muitas vezes, existem vários formatos para imagens adicionais.
Adicionar novas dimensões a um aplicativo existente também causa algumas dores de cabeça. Daí a tarefa:

Tarefa

Vamos denotar a lista de requisitos:

  • Gerar imagens adicionais de qualquer formato dinamicamente sem introduzir funcionalidades adicionais no aplicativo a qualquer momento durante a existência do aplicativo;
  • Imagens adicionais não precisam ser geradas em todas as solicitações;
  • Desative a capacidade de gerar imagens adicionais de formatos não especificados.

Explicarei o último ponto, porque contradiz ligeiramente o primeiro ponto. Se abrirmos a geração de alguma imagem, existe a possibilidade de um ataque ao site gerando um grande número de solicitações de redimensionamento da imagem em um número infinito de formatos, portanto esta vulnerabilidade precisa ser fechada.

configuração de instalação do nginx

Para resolver os requisitos acima, precisamos do seguinte conjunto de módulos nginx:

Módulos ngx_http_image_filter_module и ngx_http_secure_link_module não são instalados por padrão, portanto devem ser especificados no estágio de configuração da instalação nginx:

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

configuração nginx

Adicionamos um novo à nossa configuração de host localização e parâmetros gerais de cache:

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

Também adicionamos um novo host à configuração:

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

Como resultado, imagens adicionais podem ser obtidas através dos seguintes links:

* try_files - sensível a espaços e caracteres russos, então tive que fazer uma muleta com aliás.

Use em um aplicativo da web

No nível da aplicação web, você pode fazer o seguinte procedimento (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'
                );

Embora eu também recomende calcular os tamanhos visualização.

Ancinho

Ao excluir a imagem original, as visualizações, naturalmente, não serão excluídas do cache até que o cache seja invalidado e, no nosso caso, as visualizações podem existir por um dia após a exclusão, mas este é o tempo máximo.

original

Fonte: habr.com

Adicionar um comentário