Ubah saiz imej dengan pantas

Dalam hampir mana-mana aplikasi web yang menggunakan imej, terdapat keperluan untuk mencipta salinan kecil imej ini, dan selalunya terdapat beberapa format untuk imej tambahan.
Menambah dimensi baharu pada aplikasi sedia ada juga menyebabkan beberapa pening kepala. Oleh itu tugas:

Petugas

Mari kita nyatakan senarai keperluan:

  • Hasilkan imej tambahan bagi sebarang format dengan segera tanpa memperkenalkan fungsi tambahan ke dalam aplikasi pada bila-bila masa semasa kewujudan aplikasi;
  • Imej tambahan tidak perlu dihasilkan pada setiap permintaan;
  • Lumpuhkan keupayaan untuk menjana imej tambahan daripada format yang tidak ditentukan.

Saya akan menerangkan perkara terakhir, kerana ia sedikit bercanggah dengan perkara pertama. Jika kita membuat penjanaan mana-mana imej terbuka, maka terdapat kemungkinan serangan ke atas tapak dengan menjana sejumlah besar permintaan untuk mengubah saiz imej kepada bilangan format yang tidak terhingga, jadi kelemahan ini perlu ditutup.

konfigurasi pemasangan nginx

Untuk menyelesaikan keperluan di atas, kami memerlukan set modul nginx berikut:

Modul ngx_http_image_filter_module ΠΈ ngx_http_secure_link_module tidak dipasang secara lalai, jadi ia mesti dinyatakan pada peringkat konfigurasi pemasangan nginx:

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

konfigurasi nginx

Kami menambah yang baharu pada konfigurasi hos kami lokasi dan parameter cache umum:

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

Kami juga menambah hos baharu pada konfigurasi:

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

Hasilnya, imej tambahan boleh diperoleh menggunakan pautan berikut:

* try_files β€” sensitif kepada ruang dan aksara Rusia, jadi saya terpaksa membuat tongkat dengan alias.

Gunakan dalam aplikasi web

Di peringkat aplikasi web, anda boleh melakukan prosedur berikut (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'
                );

Walaupun saya juga akan mengesyorkan mengira saiz preview.

Rake

Apabila memadamkan imej asal, pratonton, secara semula jadi, tidak akan dipadamkan daripada cache sehingga cache tidak sah, dan dalam kes kami, pratonton boleh wujud selama sehari selepas pemadaman, tetapi ini adalah masa maksimum.

yang asal

Sumber: www.habr.com

Tambah komen