5-минутный кэш файлов в PHP

У меня очень простой вопрос: какой способ загрузки файла на PHP лучше всего, но только если локальная версия была загружена более 5 минут назад?

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

$file = file_get_contents($url); 

без локальной копии или кеширования. Каков самый простой способ преобразовать его в кешированную версию, где конечный результат не изменяется (файл $ остается таким же), но он использует локальную копию, если она была получена не так давно (скажем, 5 минут)?

Solutions Collecting From Web of "5-минутный кэш файлов в PHP"

Используйте локальный файл кеша и просто проверяйте время существования и модификации файла, прежде чем использовать его. Например, если $cache_file – это имя файла локального кэша:

 if (file_exists($cache_file) && (filemtime($cache_file) > (time() - 60 * 5 ))) { // Cache file is less than five minutes old. // Don't bother refreshing, just use the file as-is. $file = file_get_contents($cache_file); } else { // Our cache is out-of-date, so load the data from our remote server, // and also save it over our cache for next time. $file = file_get_contents($url); file_put_contents($cache_file, $file, LOCK_EX); } 

(Непроверенный, но на основе кода, который я использую в данный момент.)

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

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

Если вы беспокоитесь о блокировке и одновременном доступе, я бы сказал, что самым чистым решением будет файл_put_contents во временный файл, а затем rename() его поверх $cache_file , который должен быть атомарной операцией, то есть $cache_file будет либо старое содержание или полное новое содержание, никогда наполовину не написанное.

Попробуйте phpFastCache , он поддерживает кеширование файлов, и вам не нужно кодировать свой класс кеша. простой в использовании на общем хостинге и VPS

Вот пример:

 <?php // change files to memcached, wincache, xcache, apc, files, sqlite $cache = phpFastCache("files"); $content = $cache->get($url); if($content == null) { $content = file_get_contents($url); // 300 = 5 minutes $cache->set($url, $content, 300); } // use ur $content here echo $content; 

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

  • Идентификатор; что вы можете использовать для получения файла в следующий раз, когда вам это нужно. Возможно, что-то вроде имени файла.
  • Временная метка с последнего раза, когда вы загрузили файл из URL-адреса.
  • Либо путь к файлу, где он хранится в локальной файловой системе, либо поле типа BLOB, чтобы просто сохранить содержимое самого файла в базе данных. Я бы рекомендовал просто сохранить путь лично. Если файл был очень большой, вы определенно не захотели бы поместить его в базу данных.

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

Если у вас нет настройки базы данных, вы можете сделать то же самое, просто используя файлы, в которых один файл или поле в файле будет содержать метку времени при последнем скачивании файла.

Во-первых, вы можете проверить шаблон дизайна: ленивая загрузка .

Реализация должна измениться, чтобы всегда загружать файл из локального кеша. Если локальный кеш не существует или дрожит время файла более 5 минут, вы извлекаете файл с сервера.

Псевдокод выглядит следующим образом:

 $time = filetime($local_cache) if ($time == false || (now() - $time) > 300000) fetch_localcache($url) #You have to do it yourself $file = fopen($local_cache) 

Вот простая версия, которая также передает строку User-Agent Windows на удаленный хост, чтобы вы не выглядели как создатели проблем без соответствующих заголовков.

 <?php function getCacheContent($cachefile, $remotepath, $cachetime = 120){ // Generate the cache version if it doesn't exist or it's too old! if( ! file_exists($cachefile) OR (filemtime($cachefile) < (time() - $cachetime))) { $options = array( 'method' => "GET", 'header' => "Accept-language: en\r\n" . "User-Agent: Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)\r\n" ); $context = stream_context_create(array('http' => $options)); $contents = file_get_contents($remotepath, false, $context); file_put_contents($cachefile, $contents, LOCK_EX); return $contents; } return file_get_contents($cachefile); } 

Вы можете сохранить копию своего файла при первом попадании, а затем проверить с filemtime метку времени последней модификации локального файла при следующих хитах.

Вы бы деформировали его в кеш, как метод:

 function getFile($name) { // code stolen from @Peter M if ($file exists) { if ($file time stamp older than 5 minutes) { $file = file_get_contents($url) } } else { $file = file_get_contents($url) } return $file; } 

Я думаю, что вам нужна какая-то (psuedo-код) логика вроде:

 if ($file exists) { if ($file time stamp older than 5 minutes) { $file = file_get_contents($url) } } else { $file = file_get_contents($url) } use $file