Pull to refresh

Comments 65

т.е. картинка 150x100 в браузере у клиента будет иметь физический размер 1680х1050 и весить 5 метров?
нет… вы не поняли… в первый запрос картинки не существует, запрос обработает рнр-скрипт и создаст необходимую миниатюру нужного размера
Ну да… есть еще один недостаток — объект-владелец оригинальной картинки ничего не знает о ее копиях. Но это впринципе легко поправимо — на уровне работы с картинками — при удалении пробегаться еще по каталогам ресайзов в поисках картинки с таким же именем и частичным путем

а можно просто периодически убивать весь каталог с ресайзами )))
Считаю что 404 это уже лишнее. Что вам мешает указать путь к пхп скрипту в src атрибуте изображения? этот скрипт и будет уже делать то что надо, проверять, генерить и тп?
Мне почему-то хотелось чтобы скрипт не отрабатывал вызов каждой-каждой картинки и миниатюры.

Думаю в случае высоко нагруженных систем это имеет смысл.
Такой вариант хорош, когда нужно считать количество просмотров.
количество просмотров считать можно совсем другим софтом и более того лучше это делать другими специфичными программами со своей бд и прочее которые собирают подобного рода статистику
совсем не лишнее потому как подымать пхп на отдачу картинок вот это уже совсем безграмотно, на высокой нагрузке это будет оооочень плохо когда статику отдает нжинкс, но согласен с тем что необходимо подумать и избавится от обработки 404ой
вы противоречите себе :) подымать пхп плохо и 404 плохо. Совсем хорошо небывает :)
Я считаю что 404 плохо, лучше уж подымать пхп, это первое что пришло в голову, если конкретно заняться проблемой то наверное лучше генерить превьюшки сразу а не налету.
Вообще пытаюсь выйти из дискуссии в этом топике только не могу не ответить на ответ :)
не вижу противоречия, если бы мы имели два варианта либо 404 либо подымать пхп то это можно было бы расценить как противоречие но ни мне ни вам всего количества вариантов решения данной задачи неизвестно поэтому никаких противоречий тут нет, для меня если вы не поняли из моего топика поднимать пхп хуже нежели обрабатывать 404ую внизу я высказался на эту тему более развернуто
Прочитал ваш пост снизу. Вот мы и сошлись в мнении что лучше их генерить сразу :) могу спокойно уйти на пенсию :)
Лучше юзать mod_rewrite. Там есть замечательный RewriteCond !-f (по-моему, точно не помню), тогда надо будет дёргать пхп только если нет картинки.
Если разрешать вручную указывать любой размер через изменение урла, то очень уж легко можно задосить сервак…
Я бы использовал предефайнутые типы картинок, которые можно задавать в конфиге того же шаблона.
Да… согласен… а то пару запросов с ресайзом до 1000000… и нет больше места на диске ))
ну если это пых и используется gd то там ограничение внутреннее есть до нескольких МБ
Решение по экономии места на диске родилось такое — после рисайза сохраняется изображение с указанием реальных размеров (после рисайза) в имени файла и создается symlink на этот файл с указанием запрошенных размеров в имени линка.

Таким образом если запрос картинки из разных частей шаблона (например 400x400 и 400x300) преобразует ее к одному и тому же реальному размеру (например 400x200) то процесс рисайза пройдет один раз и файл сохранится в единственном экземпляре с несколькими линками на него.

Вызов скрипта рисайза у нас реализован через mod_rewrite.
А что помешает мне, как злому какеру, загнать запрос к картинке в цикл и каждый проход увеличивать запрашиваемые размеры на единицу?..
Некоторых злоумышленников можно отсечь проверяя поле referer заголовка запроса.

И, естессно, не ресайзить в сторону увеличения (можно сохранять линки на оригинал) и ограничить разумными размерами сверху.

Но, вопрос интересный. Спасибо за подсказку.
$_GET['w'] = min($_GET['w'], 1200);
$_GET['h'] = min($_GET['h'], 1200);
Остается еще 1200*1200*n = 1440000*n ресайзов, где n — количество картинок на сервере.
>>Надеюсь что не велосипед изобрел…
насколько я помню, так работает модуль imagecache в друпале.
а на код можно как-нибудь посмотреть?
Также в cs-cart используется такая система (там всё в конфигах хранится, не подосишь особо), но там рисунки отдаются через php скрипт, так что идея конечно далеко не нова (что и не удивительно — довольно популярная проблема), автор напрасно думал что на него снизошло прозрение божье =)
Зачем 404я? Огород Вы городите, если честно… Почему аналогичный скрипт, даже с кешированием на диске, нельзя сделать через обычный script.php?src=, как уже говорилось выше.

Что касается кеша и сборщика мусора — здесь должно быть два аспекта, как минимум:
1) Удаление всего, что старше, допустим, месяца
2) Установка миниатюре даты создания оригинальной картинки (через touch() например) — а в скрипте эти даты сравнивать и т.о. вычислять актуальность

Еще немаловажно старательно рассматривать параметры вызова, ибо вызвав 100 раз уменьшалку с разными размерами со 100 машин будет достаточно, чтобы любой шаред хостинг заблокировали. Так что к двум пунктам можно дописать еще один — суммарное кол-во миниатюр, и их размер.

Если пойти еще дальше — можно при наличии бОльших «кратных» размеров отдавать их, не сжимая на сервере. Браузер сам сожмет картинку 200 пикселей в 100 или 50 практически без потерь в качестве.
вам уже ответили почему 404 лучше — в случае высоконагруженого проекта php для ресайза вызовется только один раз, а в предложеном вами варианте — будет вызываться снова и снова, создавая лишнюю загрузку на сервер.
Врядли на крупном проекте понадобится подобное решение.
«будет вызываться снова и снова» вообще-то скрипт может вернуть уже имеющийся файл, проверив его существование.

Вы думаете, ошибка 404 не вызовет нагрузки, если там все равно стартует РНР скрипт ;)?
Даже если скрипт просто вернет готовую картинку, это означает что вызовется php, а это уже большие накладные расходы при высоких нагрузках.
На нашем проекте (более 400 запросов в секунду) мы применяем такой подход при отдаче новостей — если новость смотрят первый раз — 404 обработчик в nginx дергает php и тот отдает страницу и ложит ее в файл. В дальнейшем — nginx просто отдает статический файл (очень быстро) и не трогает php. Вот планируем и картинки перевести на такую генерацию (сейчас заранее делаем все размеры для каждой картинки).
В случае такой посещаемости разумнее картинки сжимать либо при закачке, либо вообще по ночам или когда нагрузка спадает, и вообще всегда отдавать как статику. Плюс что-то мне подсказывает, что большинство миниатюр хотя бы раз, но отсмотрены будут, поэтому «ненужные» изображения вряд ли будут.

Что касается PHP — я подразумевал, что картинка (оригинал) может быть изменена и поэтому есть необходимость обновлять миниатюры. А в таком случае уже все равно, как вызывается скрипт.

Если же картинки закачиваются одноразово — то Ваш вариант вполне хорош, особенно с использованием nginx.
только вот в вашей схеме если картинка поменяется то придется вычищать все ее миниатюры, ну либо заботиться об уникальности файлов — тогда это будет помойка
Этот топик не теорема а аксиома. Тут не обсуждают, тут рассказывают как надо делать!
«Не говорите, что мне делать, и я не скажу, куда Вам идти.»

В web-разработке аксиом не бывает. Для разных задач следует применять разные способы решения.
UFO just landed and posted this here
а кто-то отменил реврайты?
для apache:
RewriteCond %{REQUEST_URI} ^(.+)/images/(.+)$
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule ^(.+)$ image\.php?$1 [L]


если урл вмещает в себя /images/, и такой файл физически не существует, то запрашивается скрипт
куча правил мод реврайту тоже не очень хорошо и тоже тормоза там где можно просто отдать файл лучше его просто отдать

после некоторых размышлений пришел к выводу что лучше делать сразу все превью всех необходимых размеров и иметь скрипт который мог бы по крону это проверять а потом просто отдавть нужный файл, мы теряем в месте на сервере, хотя потеря эта очень зависит от специфики проекта, но выигрываем в производительности, имхо место на сервере гораздо более дешевый ресурс нежели производительность
странные вещи говорите)
какая куча правил? я представил только одно, нужное для задачи. и не «мод реврайту», а для apache.
я думаю, что операция проверки на существование файла сервером перед его отдачей — операция тривиальная, и не требует ровно никаких ресурсов, по сравнению с ресурсами на отдачу файла.

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

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

и наконец, если покажется медленным — перепишите это правило для nginx и сделайте проксирование на apache.
ну как правило количество правил растет в файле .htacess подумайте как это все будет работать если у вас файлы по разным серверам раскиданы? проверка на существование файла) уже данное решение не кажется мне хорошим, операция тривиальна но это не экономия на спичках, если отдачей файла занимается апач то да она ничего не значит эта процедура если же ей занимается нжинкс то уже не все так тривиально, конечно я понимаю что скрипт вызывается не каждый раз, в производительности мы теряем вот этот один раз + ваши правила в .htaccess
Вы считаете, что apache лучше работает со статикой?
какой один раз мы теряем в производительности? ресурсы нужны в любом случае на генерацию картинки. просто мы переносим этот момент времени чуть-чуть вперед.

а если файлы по разным серверам, то этот вариант совершенно не подходит в корне. и не потому, что он как бы «медленный». а потому, что надо хранить путь к превью включая сервер, на котором оно находится. соотвестветнно, генерить надо другим методом.
Упс, долго писал, когда отпостил, увидел и Ваш комментарий :)
Да, вариант с mod_rewrite не медленный. И дает хорошую гибкость. Плюс, такой момент. Ответ 404 посылается и в заголовках. В apache можно переназначать 404ю страницу. Можно и изменить заголовки ответа сервера в скрипте. Но что будет, если апач сделал редирект на 404, то есть на скрипт, а скрипт вдруг умер?
) наверно путано изъяснился, нет конечно я не считаю что апач лучше со статикой работает)
один раз когда делаем тамб по запросу теряем в производительности) + теряем в производительности когда выполняем правила из хтакцесса

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

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

и кстати если задуматься то вам ничего не мешает хранить путь к оригиналу сразу вместе с сервером) и в данном случае это не является причиной по которой данный метод не может работать.
а Вы думаете, что когда сервер отдает 404-ю ошибку, он не проверяет на наличие файла?
по-моему Вы в корне неправы со своей «оптимизацией».

при описываниии правила мы делаем эту же проверку, только до того, как апач будет пытатся выдать этот контент.
ну чтож вы так категорично то настроены) при описании правила мы делаем этуже проверку конечно но увы сервер ее сделает быстрее чем мы с нашими правилами в этом я уверен на 100%) повторюсь мне не нравится как вариант с отдачей из пхп так и вариант с 404 так и вариант с мод реврайтом
можно еще бинарные данные в БД хранить.
Если файлы раскиданы по разным серверам, которые к примеру являются поддоменами, то и запросы на картинку будут вида domen1.site.ru/image/h150/image.jpg. И отрабатывать будет mod_rewrite на соответствующем сервере.

Данное решение можно сделать частью распределенной файловой системы, которая сама на себя берет раскидывание файлов по серверам, генерацию урлов, для верстальщика нужно только указывать размер, и система отдает ему урл. Также система управляет миниатюрами, обновляет их при изменении файла. Но DFS это отдельная тема :)
если используются поддомены) для хранения статики что вобщемто не является общим решением и связано с дополнительными административными заморочками
Само собой. Вариантов много, я привел один из них, не уточнил это.
Хотя например что в одноклассниках что в контакте вся статика тащится с поддоменов в фейсбуке незнаю но наверно точно также, представляется оптимальным вариантом но все равно решение с мод реврайтом мне не по душе но как говорится на вкус и цвет
А зачем это в корень кидать? Apache может обработать .htaccess папки images.

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

Сейчас сделали один универсальный ресайзер, который отдает картинки через себя (сравнивая eTag и Last-Modify). Этот ресайзер ведет базу копий и сверяет дату копии и дату оригинального файла. Если отличаются — обновляет копии. Этот же ресайзер обучен многим другим полезным вещам, от масштабирования изображения разными способами, до подключение ватермарков и иконок к картинкам.
да да насчет недостатка согласен тоже думал на эту тему, мне наиболее универсальным и хорошим решением кажется создание всех превьюх сразу при заливке картинки, а не по необходимости, не так уж часто количество превью больше 3ех как мне кажется, с другой стороны вариантов конечно может быть много с ватермарком без вотермарка с маштабом по большей стороне с обрезанием и т.д. вобщем как выясняется не такой уж тривиальный вопрос), всеже необходимо исходить из требований проекта которые как всем известно могут меняться по 100 раз)))
>наиболее универсальным и хорошим решением кажется создание всех превьюх сразу при заливке картинки

А вот это решение гибким мне не кажется. Если понадобится делать редизайн проекта и менять размер превьюх — будет проблема. В случае, который описан в статье надо будет только переписать код и очистить кеш от старых файлов, остальное будет сделано автоматически.
ну проблема весьма условная напишите скрипт который будет из оригиналов делать новые превью в соотвествие с новыми размерами, как например это реализовано в Drupal их модуль имажес и функциональность миниатюр
Вам же уже пытались объяснить выше — весь плюс данного метода в том, что при повторных вызовах миниатюры РНР не вызывается. Вообще. Картинка отдается напрямую апачем либо нгиниксом.
Как при таком пододе вы определите что нужно сделать новое превью?
послушайте я прекрасно понимаю что мне хотят объяснить) просто пытаюсь вести дискуссию на более широкую тему, если вы до сих пор не поняли смысла моих комментов, всю суть указанного в топике метода я прекрасно понимаю, просто пытаюсь ответить какой метод был бы удобен лично мне) когда мы заранее знаем какие превью нам нужны мы их сразу все и создаем) при том подходе который предлагаю я мы знаем форматы всех превью и новых делать не нужно если вы досих пор не поняли смысла моих комментов. Дискуссия давно вышла за рамки темы топика поэтому не стоит меня упрекать в том что я раздуваю флуд.
в этом методе пхп вообще не вызывается) наша задача сделать так чтоб код вообще не исполнялся)
> в этом методе пхп вообще не вызывается

ага. а превью святой дух делает.

> К сожалению у этого способа есть огромнейший минус — если оригинальную картинку заменят ее копии не обновятся

Может быть, система, где заливаются картинки, будет осведомлена о возможности существования миниатюр — и будет их просто убивать при изменении оригинала?
ну если честно этот недостаток тоже весьма условен, когда ктото гдето убивает оригинал то все миниатюры убиваются тоже, если ктото заливает новый орригинал то все превью тоже перестраиваются этого легко добится используя нейминг в путях к картинкам например 2008/12/03/u123/весьтаймстампсмилисекундами+еще чтонить что легко получается из всего остального.jpg — как вариант, если вы понимаете о чем я
можно в путях к картинкам еще использовать их id тогда легко будут строится эти пути к картинкам и легко можно будет выбирать именно нужные превью, как видите этой проблемы вобщемто нет необходимо только позаботится и внести некоторую структуру в пути к картинкам и названия файлов картинок
ну вообще лисапед конечно, в том смысле что только мной написаны 2 реализации. от себя советы:
1. все-же всегда ходить через скрипт
2. скрипт юзает также HTTP кеширование (If-Modified-Since и т.п.)
3. вычищать кеш, как тут советовали, проверяя раз в 100 запусков например старые копии
4. на нагруженных системах существующее решение легко адаптируется путем установки принудительного кеширования например на минуту сервером (поэтому на скорость можно забить)
5. кроме размеров, как оказалось, полезно передавать еще, как минимум, 2 параметра — тип масштабирования (вписывание, обрезание) и цвет фона при вписывании как вариант можно добавить что-то типа фильтра (сепия, блур еще что)
Давно пользуюсь такой практикой — очень удобно.

После этого и работать с сайтом одно удовольствие, при добавлении статей или товаров нужно загружать одну картинку любого размера, вместо 3-4 картинок четко определенного размера.

Единственное, что размер лучше указывать в имени изображения (/resize/images/myimage-10x20.jpg), а не в пути, чтобы не создавать кучу папок, а главное удалить все изображение всех размеров будет очень просто.
Sign up to leave a comment.

Articles