Pull to refresh

Простое создание миниатюр и хранение их на Amazon S3

Reading time 3 min
Views 16K
Ни один сайт не может обойтись без генерации миниатюр изображений. В интернете можно найти миллион статей на эту тему. Возможно, кому-то пригодится и это решение.

Требования:
  • Изображения хранятся на удаленных серверах. У нас есть только ссылки на эти изображения
  • Миниатюра должна формироваться любого заданного размера в момент непосредственного обращения к ней
  • Должна быть предусмотрена защита от вредителей
  • Миниатюра должна храниться на Amazon S3 и быть доступна по поддомену основного сайта. Количество бакетов на S3 и соответственно поддоменов неограничено


Реализация:
Допустим, что имя нашего сайта domain.com

1) На Amazon S3 создаем 4 бакета с названиями ic1.domain.com, ic2.domain.com, ic3.domain.com, ic4.domain.com (названия поддоменов могут быть разными, в нашем случае – это сокращение от image cache)

2) Заходим в настройки каждого бакета и ставим галочку напротив Enable website hosting

3) В поле Edit Redirection Rules прописываем правила для редиректов с несуществующих страниц:

<RoutingRules>
    <RoutingRule>
        <Condition>
            <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <HostName>domain.com</HostName>
            <ReplaceKeyPrefixWith>s3/thumbs/</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
    <RoutingRule>
        <Condition>
            <HttpErrorCodeReturnedEquals>403</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <HostName>domain.com</HostName>
            <ReplaceKeyPrefixWith>s3/thumbs/</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
</RoutingRules>


4) Заходим в панель управления доменным именем domain.com и создаем поддомены, аналогичные названиям бакетов. В CNAME прописываем Endpoint из настроек бакета.

Что мы только что сделали:
Создали 4 поддомена, на которых будут храниться миниатюры. Каждая миниатюра будет иметь адрес типа: ic1.domain.com/miniatura.jpg

Как только к этому файлу будет первое обращение, Amazon увидит, что такого файла в бакете ic1.domain.com нет и перенаправит пользователя на указанный Вами путь, который конкатенируется из HostName + ReplaceKeyPrefixWith: domain.com/s3/thumb/miniatura.jpg

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

Остальные пользователи – будут получать ее непосредственно с Amazon S3.

Поехали дальше.
До сих пор непонятно как именно передавать параметры для минимизации и ссылку на саму картинку.
Что имеем:

Разумеется, что ссылка вида: ic1.domain.com/?Img_url=http://blablabla.com/photo15.jpg&Thumb_w=100&Thumb_h=100 нас абсолютно не устраивает, т.к. во-первых Amazon нас не поймет, а во-вторых – нет никакой защиты от вредителей.

Вариантов, как создавать такие ссылки может быть миллион. Мы решили обойтись без промежуточных таблиц или записей и посмотрели в сторону RC4 криптования. Звучит страшно. Но давайте посмотрим, что получилось:
ic2.domain.com/e2/PUuxR1p~D~Jgl5PrnPMLh4OA0sO899rjZgzgWFU_.jpg
Довольно таки милая ссылка. По крайней мере не намного страшнее чем md5 хеш. Зато намного информативнее. Если расшифровать крипт, получим:
blablabla.com/photo15:100@100
То что нам надо – все данные по фотографии, размеры и плюс ко всему, не зная пароля от крипта – никто не сможет нагенерить «лишних миниатюр»

Вопрос остался за малым – реализовать функцию, которая будет принимать ссылку на изображение, размеры и возвращать ссылку на миниатюру (ну и разумеется все остальные скрипты).

По ссылке на github некоторая реализация поставленной задачи: github.com/wolflingorg/s3thumb

Структура:
CS3Thumb.php – основной класс
S3.php – класс для работы с Amazon S3
CRC4Crypt.php – класс для криптования в RC4
CThumb.php – класс для создания миниатюр

Как использовать:
$Thumb = new CS3Thumb($backets, $accessKey, $secretKey, $cryptpsw = 'password');

Где:
$backets — массив с наименованиями бакетов (они же поддомены)
$accessKey и $secretKey – доступы к амазону
$cryptpsw – пароль для криптования ссылок

Для того, чтобы получить ссылку на изображение, используем:
$Thumb -> url("http://blablabla.com/photo15.jpg", 100, 100);

Для того чтобы создать миниатюру, переместить ее на S3 и отобразить первому пользователю:
$Thumb -> process("e2/PUuxR1p~D~Jgl5PrnPMLh4OA0sO899rjZgzgWFU_.jpg");

, где e2/PUuxR1p~D~Jgl5PrnPMLh4OA0sO899rjZgzgWFU_.jpg — то, что будет в ссылке после domain.com/s3/thumbs/(*), после редиректа с Amazon

Надеюсь, статья будет полезна. Спасибо.
Tags:
Hubs:
+21
Comments 16
Comments Comments 16

Articles