Генерация превьюшек изображений без необходимости хранить тысячи кэш-файлов на сервере

800
.
ramzes
Речь пойдет о кешировании (логично), но не на стороне сервера, а на стороне клиента.
До сих пор я не мог найти подобного решения в интернетах (хотя может просто плохо искал?) и придумал свое.
Что в результате?
В результате скрипт пережимает картинки до нужных размеров, в нужные форматы, накладывает копирайт (все то что делает самый обычный ресайзер картинок), но при этом не гадит на диск ни единым файлом, и не напрягает сервер постоянной повторной генерацией.
В чем фишка?
Все просто. надо просто отдать сгенерированную картинку с верными заголовками.
Мы же игнорируем факт того что файл не существует физически, что отдается он не nginx, и что заголовков в комплекте с файлом не идет.
Ближе к сути.
Отправляем заголовки до генерации картинки
header('Date: '.gmdate("D, d M Y H:i:s", time()).' GMT'); // текущее время сервера.

важный момент, служит для определения временного сдвига при сравнении браузером дат
$headers = getallheaders();
        $since =  isset($headers['If-Modified-Since']) ? strtotime($headers['If-Modified-Since']) : 0;
        $filetime = filemtime($this->file);

забираем заголовок If-Modified-Since и сравниваем его со временем изменения оригинального файла-исходника на диске.
if($since >= $filetime ){ // сравниваем

            header('HTTP/1.1 304 Not Modified');
            header('Last-Modified: '.gmdate("D, d M Y H:i:s", $filetime).' GMT');
            header('Expires: '.gmdate("D, d M Y H:i:s", (filemtime($this->file) +315360000)).' GMT');
            header('content-disposition: inline; filename="unnamed.'.$this->replaceData['type'].'"');
            header('Cache-control:  cache, public, max-age=315360000');
            header('Pragma:  cache;');
            exit;
// файл не изменился, отдаем заголовки, заканчиваем выполнение скрипта
        }else{

            header('Last-Modified: '.gmdate("D, d M Y H:i:s", $filetime).' GMT');
            header('Expires: '.gmdate("D, d M Y H:i:s", (filemtime($this->file) +315360000)).' GMT');
            header('content-disposition: inline; filename="unnamed.'.$this->replaceData['type'].'"');
            header('Cache-control:  cache, public, max-age=315360000');
            header('Pragma:  cache;');
// файл еще не кеширован, или кеш старее последнего изменения исходного файла. Отдаем  стандартные  заголовки (важно: не лепим отсебятины, делаем так как сделал бы сервер отдавая статику) браузер их запоминает, и на их основе далее будет кешировать файл.
        }

Описал коротко, только самое важное, пара часов до работы, так что, тороплюсь, немного подробнее описал тут http://blog.smartoff.net/blog/16/
Спасибо за внимание
.
результат повторного запроса к ресайзеру выглядит вот так: http://blog.smartoff.net/stora ... 4.jpg
.
Enter нажат, к чему теперь рыданья…
ramzes, прикольно. А робот Гугла как реагирует на это всё, пробовал? Понимает он такую оптимизацию или нет? От этого ведь зависит ранжирование, хотя и не самый важный момент, но всё же.
В конце концов можно просто настроить Nginx на время кеширования статики и не париться с заголовками.
.
ramzes
Sitego, ни робот, ни человек, не найдет различий между статикой и генерированным изображением.
это не обман, это просто правильная отдача файла.
если нужно более надежное подтверждение, просмотри заголовки скриншотов в гугл.плей (на сайте) и там будет точно то же, буквально 1в1
там тоже используется динамическая генерация изображений
.
Enter нажат, к чему теперь рыданья…
ramzes, я просто о том, что имеет ли смысл писать лишний код, если в настройках сервера уже есть время кеширования статических файлов?
Например, сервер отдаёт заголовок на картинках Expires: Thu, 31 Dec 2037 23:55:55 GMT, значит браузер запомнит, что этот файл нужно брать из кеша всегда, пока будет существовать сам кеш, и дёргать сервер он всё равно не будет.
.
ramzes
вот тут ты упускаешь важный момент.
генерированная картинка выведенная прямо в браузер - это не файл. это просто строка.
отдает его не сервер, а пхп.
ни какие настройки отдачи файла сервером не влияют на поток (читай строка текста) отданный пхп
.
Sitego
Enter нажат, к чему теперь рыданья…
Я чего-то немного запутался. Вот например, если сервер отдал заголовок время кеширования, заходит пользователь №1 - браузер скачал сгенерированную картинку-превьюшку которая хранится на сервре и запомнил, в следующий раз он зайдёт, картинка уже есть в кеше, она не будет скачиваться. Зайдёт пользователь №2, он снова скачает эту картинку, потому что у него в кеше нет такой картинки, ну и так далее, третий, четвёртый пользователь.
Теперь рассмотрим твой вариант. На сайте нет превьюшки, заходит пользователь №1, картинка генерируется и отдаётся ему, браузер по твоим заголовкам запоминает и ложит её в кеш, в следующий раз он уже не будет качать картинку, она есть в кеше и генерировать её уже не нужно. Заходит пользователь №2, на сервере нет превьюшки, значит снова происходит генерация. И так далее, много пользователей, много генераций. Так я понял или нет? Тогда в чём оптимизация?
Оптимизация разве что в месте на диске?
.
да. для каждого генерируется по новой.
почему так, и зачем?
обьясню.
как пример главная моего сайта, вес 5мб (куча графики)
вес с применением ресайзера 1.3 мб. вес с применением ресайзера + чекера поддержки webp примерно 800кб.
5мб - 800кб.
представь экономию?
если сделать статический кеш на диске, то это +2 файла к каждому существующему, и еще +2 файла в формате webp.
адовое кол-во места.
ах да. я как человек добрый, гостям графику отдаю с копирайтом, а своим без. еще +4 файла.
сама по себе гибкость генерации на лету очень удобна, но всегда мешало отсутствие кеширования таких картинок. вот и решение
сейчас у меня генерится где то 40 картинок на странице, сервер даже не замечает этого.
.
человек И пароход
не вкурил чет.
насколько понял, в классическом варианте изображения обработались и лежат себе на сервере.
в твоем варианте частенько будут заново обрабатываться.
А если зайдет 1000 новых человек и для каждого сервер что будет по новой все обрабатывать?
А если 20 000 ?
В чем идея?
.
Enter нажат, к чему теперь рыданья…
ramzes, по сути Crack правильно говорит. Если большая посещалка будет, например, поймаешь Хабраэффект, то процессор на сервере сдохнет и оперативка в аут уйдёт, сервер просто ляжет и не встанет.
Всего: 24