Подтвердить что ты не робот

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

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

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

$file = file_get_contents($url);

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

4b9b3361

Ответ 1

Используйте локальный файл кеша и просто проверяйте время существования и модификации файла перед его использованием. Например, если $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() it над $cache_file, который должен быть атомной операцией, т.е. $cache_file будет либо старым содержимым, либо полным новым содержимым, никогда не написанным на полпути.

Ответ 2

Попробуйте 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;

Ответ 3

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

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

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

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

Ответ 4

Сначала вы можете проверить шаблон дизайна: Lazy loading.

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

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

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

Ответ 5

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

<?php

function getCacheContent($cachefile, $remotepath, $cachetime = 120){

    // Generate the cache version if it doesn't exist or it 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);
}

Ответ 6

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

Ответ 7

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

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;
}

Ответ 8

Я думаю, вам нужна какая-то (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