Ресайзинг изображений на сайте. Как сделать это удобно?

Когда на сайте используется изображение в различных размерах, например,  когда обложка музыкального диска должна отображаться в нескольких размерах, многие разработчики чего только выдумывают, чтобы реализовать эту функциональность. Например, после закачки картинки, делается несколько копий картинки и кладется на диск. Некоторые вообще везде используют оригинальную картинку, а когда нужно, “меняют” ее размер, выставляя нужную высоту и ширину в теге img - такое встречается повсеместно (за такое решение нужно кое-что отрывать).

Я расскажу, как сделать ресайзинг картинок по-запросу. Впервые, я использовал это решение в 2004 году в одном из проектов, над которым я работал. Идея проста до безобразия.

Давайте представим, что у вас есть оригинальное изображение, размером 1000х1000 пикселей. Вам нужно использовать уменьшенные копии этого изображения в различных местах сайта в размерах 300х300, 200х200 и 50х50 пикселей.

Вы закачиваете оригинальное изображение на сайт через форму и оно распологается здесь, от document_root:

/pictures/777.jpg

Теперь, на одной из страниц сайта, вы хотите показать это изображение, но в размере 200х200 пикселей, и вы вставляете на странице тег:

<img src="/pictures/200x200/777.jpg" />

и - вуаля - картинка в нужном вам размере отображается на странице! Как это сделано? Довольно просто. Нам всего лишь нужно перехватить все обращения веб-сервера к несуществующим картинкам. Для этого напишем правило в .htaccess и положим его в document_root:

<IfModule mod_rewrite.c>
   RewriteEngine on
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-l
   RewriteRule ^(pictures/\d+x\d+/\d+.+)    resize.php?image_path=$1
</IfModule>

Теперь все обращения к несуществующим картинкам в папке /pictures будут передаваться в скрипт resize.php, расположенный в корне. В скрипт будет передаваться путь к несуществующей картинке относительно document_root.

Скрипт приводить я не буду - оставлю реализацию вам. Я только укажу, что необходимо предусмотреть в скрипте.

  • Определить путь к оригинальному изображению.
  • Нужно проверить существование оригинального изображения. Если оно не существует, вернуть 404-ю ошибку.
  • Нужно получить из пути к запрашиваемой картинки требуемую ширину и высоту.
  • Если оригинальное изображение существует и существует запрашиваемая директория (например /pictures/200×200 - это даст защиту от указания произвольных размеров картинки), то изменяем размер картинки при помощи ImageMagick или GD и сохраняем картинку по запрашиваемому пути. Затем делаем на внось созданную картинку внутренний редирект (например, Location: /pictures/200×200/777.jpg).

После реализации подобного скрипта наша система ресайзинга картинок готова. Скрипт будет изменять размер картинки только один раз. Если запрашиваемая заресайзенная картинка уже существует, то скрипт изменения размера даже не будет запускаться - правило в .htaccess не сработает, всю работу выполнит веб-сервер.

Я знаю, что подобное решение использую не я один =). Но надеюсь, моя заметка поможет тем, кто не знал о подобном решении.

Also interesting

Tags: , , ,

7 Responses to “Ресайзинг изображений на сайте. Как сделать это удобно?”

  1. Saint_Byte says:

    Все конечно хорошо , но у ресайз картинок это очень затратная по ресурсам штука - и проход поисковика может вызвать проблемы с местом на диске и производительностью =)

    • Ouch! says:

      Ну ты не забывай, что это всего лишь пример. На боевом проекте можно сделать проверку на поисковых ботов в .htaccess. Либо, пробежаться по всем страницам сайта своим роботом, чтобы картинки заресайзились.

      Да мало ли способов!
      К тому же, как показывает практика - обычно все картинки ресайзятся до прихода роботов, благодаря обычным посетителям, которые просматривают эти самые странички.

      • Saint_Byte says:

        Дык, вот так и начинаются проблемы с производительностью. Надо подходить к разработке исходя из того что имеется не супер пуппер кластер в 1000 серверов. А относительно современный сервер. А относительно соврменный сервер это примерно 2х по 3Ггц. Вот а теперь засеки сколько ресайзиться картинка в 9 мегапикселей (средние значение у современных фотиков) а теперь попробуй ресайзить их 10 штук одновременно.

        • Ouch! says:

          Никто не мешает при закачке ресайзить картинку до приемлемых значений. Данный мною подход сделан для дальнейшего удобства при ресайзинге картинок, когда тебе нужно несколько размеров одной и той же картинки.

          Мы использовали этот подход на проекте с 500 000 хитов в сутки. Нагрузки вообще никакой не было замечено.

          Конечно, к каждому техническому решению нужно подходить с умом, не существует идеального универсального решения.

  2. Stepan Tanasiychuk says:

    да. это хороший вариант. ещё на статику можно поцепить проксирующий сервер (типа nginx) и тогда после ресайза картинки апач вобще дергаться не будет.

    • Ouch! says:

      Согласен. Но фронтенд нужен в основном для медленных клиентов, которые долго что-то закачивают или наоборот, скачивают (соединение долго не разрывается). А так и апач плюется статикой только в путь.

  3. Arqus says:

    как это проделать на asp?

Leave a Reply