У меня очень простой вопрос: какой способ загрузки файла на PHP лучше всего, но только если локальная версия была загружена более 5 минут назад?
В моем фактическом случае я хотел бы получить данные из удаленно размещенного csv-файла, для которого я в настоящее время использую
$file = file_get_contents($url);
без локальной копии или кеширования. Каков самый простой способ преобразовать его в кешированную версию, где конечный результат не изменяется (файл $ остается таким же), но он использует локальную копию, если она была получена не так давно (скажем, 5 минут)?
Используйте локальный файл кеша и просто проверяйте время существования и модификации файла, прежде чем использовать его. Например, если $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;
Если вы используете систему баз данных любого типа, вы можете кэшировать этот файл там. Создайте таблицу для кешированной информации и дайте ей минимум следующие поля:
Теперь, когда вы запускаете скрипт выше следующего раза, сначала проверьте базу данных для идентификатора и потяните отметку времени. Если разница между текущим временем и сохраненной меткой времени превышает 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