Перестроить кэш изображений
У меня есть поле изображения для каждого узла, которое выполняется через кэш изображений. Поскольку imagecache кэширует по требованию, файлы/варианты кэша не создаются до тех пор, пока они не будут запрошены в первый раз. Поэтому, если я обновлю кучу изображений, повторно разверну или иным образом уничтожу весь кэш, первый посетитель должен обработать этот файл.
Как я могу сэкономить этому пользователю время загрузки и вручную перестроить весь кэш?
В последний раз, когда это произошло, я программно загрузил каждый узел связь с jquery...
Кажется идеальным плагином Drush... вероятно, следует подумать о том, чтобы написать это, но мне любопытно, есть ли у кого-нибудь еще решение для этого.
6 answers
Вы можете создать пользовательский модуль, а затем использовать hook_cron() для восстановления ячейки изображений.
Обновление
Я только что потратил последний час, пытаясь понять, как это сделать на стороне сервера, и я думаю, что взломал его.
/**
* Implements hook_cron().
*/
function rebuildimagecache_cron() {
global $base_url;
// get published nodes
$result = db_query('SELECT nid FROM {node} WHERE status = 1');
while ($nodes = db_fetch_array($result)) {
$node = node_load($nodes['nid']);
$node_type = $node->type;
// get cck fields for the current nodes node_type
$fields = content_fields(NULL, $node_type);
foreach ($fields as $key => $value) {
// only deal with file fields that use the image widegt tyoe
if ($value['type'] == 'filefield' && $value['widget']['type'] == 'imagefield_widget') {
$preset_tokens = explode('_', $value['display_settings']['full']['format']);
$imagecache_preset = $preset_tokens[0];
$field_name = $value['field_name'];
// iterate over each field instance
foreach ($node->$field_name as $field_instance) {
$filepath = $field_instance['filepath'];
$cachedpath = imagecache_create_path($imagecache_preset, $filepath);
file_get_contents($base_url . base_path() . $cachedpath);
}
}
}
}
}
Как это работает:
- Получить все опубликованные узлы
- Для каждого узла получает тип узла
- Получает массив полей для текущего узла, который повторяется
- Перебирает все поля и проверяет, есть ли какие-либо поля изображений
- Если поле изображения найдено, то получите предустановку кэша изображений, связанную с
- Перебирать экземпляры полей изображений узла
- Для каждого экземпляра поля изображения получить путь к файлу изображения
- Преобразовать путь к файлу изображения в путь к кэшу изображения
- Прочитайте путь к файлу с помощью file_get_contents() по протоколу HTTP, чтобы заставить кэш изображений генерировать кэшированное изображение.
Я протестировал его, и он отлично сработал для меня в Drupal 6. Версия Drupal 7 была бы немного сложнее из-за изменения в базовом файловом API.
Вам нужно будет создать пользовательский модуль и вставить в него эту функцию. Убедитесь, что вы также изменили имя крючка с rebuildimagecache
на имя вашего пользовательского модуля.
Я использовал hook_cron()
, чтобы он запускался при запуске cron, но вы можете запустить его вручную с помощью команды drush
.
Низкотехнологичный подход...
- Создайте новое представление узла.
- Установите фильтр для типа контента, который содержит поля изображения.
- Добавьте поля изображения, используя любую предустановку ImageCache, которую вы хотите предварительно кэшировать.
- Установите для него значение не страница, без ограничения количества узлов.
- Загрузите представление.
- Наблюдайте, как ваш сервер ломается под нагрузкой. Если время ожидания истекло, перезагрузите представление.
О, и убедитесь, что только у администраторов есть разрешения на это представление.
Один совет по производительности: Вам не нужно загружать все содержимое изображения, чтобы вызвать кэш изображений, вы также можете просто запросить заголовки. Итак, эта строка:
file_get_contents($base_url . base_path() . $cachedpath);
Становится
get_headers($base_url . base_path() . $cachedpath);
Мое решение:
function example_cron() {
$result = db_query('SELECT fid, uri FROM {file_managed} WHERE filemime like :mime AND status = :status', array('mime' => 'image/%', 'status' => FILE_STATUS_PERMANENT));
$queue = DrupalQueue::get('generate_image_styles');
foreach ($result as $img_info) {
foreach(image_styles() as $style) {
$derivative_uri = image_style_path($style['name'], $img_info->uri);
if (file_exists($derivative_uri)) continue; // skip existing files
$data = (object) array(
'style' => $style,
'img_info' => $img_info,
'derivative_uri' => $derivative_uri
);
$queue->createItem($data);
}
}
}
function example_cron_queue_info(){
$queues['generate_image_styles'] = array(
'worker callback' => '_example_generate_image_styles',
'time' => 30
);
return $queues;
}
function _example_generate_image_styles($data){
if (!file_exists($data->derivative_uri)) {
image_style_create_derivative($data->style, $data->img_info->uri, $data->derivative_uri);
}
}
Была попытка заставить работать такие вещи, см. Пакет Imagecache, но я не уверен, на каком этапе находится разработка этих функций. Вы не упоминаете, имеете ли вы дело с D6 или D7, но я бы изучил действия и правила в 6.x-2.x-dev и посмотрел, где это находится.
Это было сделано и хорошо работает, смотрите здесь https://drupal.org/node/587086
Попробуйте установить полное исправление файла в конце потока. Убедитесь, что вы запускаете его внутри /sites/all/modules/imagecache/imagecache.drush.inc
, а не в корне, как обычно.