curl 5-PHP中的文件缓存

fnvucqvd  于 2023-03-12  发布在  PHP
关注(0)|答案(9)|浏览(158)

我有一个很简单的问题:下载PHP文件的最佳方式是什么,但前提是本地版本已在5分钟前下载?
在我的实际情况中,我希望从远程托管的csv文件中获取数据,我目前使用

$file = file_get_contents($url);

没有任何本地副本或缓存。将其转换为缓存版本的最简单方法是什么?在缓存版本中,最终结果不会改变($file保持不变),但如果它是在不久前(比如5分钟)获取的,它将使用本地副本。

h7appiyu

h7appiyu1#

使用本地缓存文件,在使用前检查文件是否存在以及修改时间即可,例如:$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);
}

(未经测试,但基于我目前使用的代码。)
无论使用哪种方法,$file最终都是您需要的数据,如果缓存是最新的,它将使用该高速缓存,如果缓存不是最新的,它将从远程服务器获取数据并刷新缓存。
编辑:自从我写了上面的文章之后,我对文件锁定有了更多的了解。如果你关心这里的文件锁定,读一读this answer可能是值得的。
如果您关心锁定和并发访问,我会说最干净的解决方案是将file_put_contents放到一个 temporary 文件,然后通过$cache_file执行rename(),这应该是一个原子操作,即$cache_file要么是旧内容,要么是完整的新内容,永远不会写一半。

zbq4xfa0

zbq4xfa02#

试试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;
ygya80vv

ygya80vv3#

这是一个简单的版本,它也会传递一个windows User-Agent字符串到远程主机,这样你就不会看起来像一个没有正确报头的麻烦制造者。

<?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);
}
siv3szwd

siv3szwd4#

如果您使用的是任何类型的数据库系统,则可以在其中高速缓存此文件。请为高速缓存的信息创建一个表,并至少为其给予以下字段:

  • 标识符;下次需要时可以用来检索文件的东西。可能是像文件名这样的东西。
  • 上次从URL下载文件的时间戳。
  • 可以是文件的路径,它存储在本地文件系统中,也可以使用BLOB类型字段将文件本身的内容存储在数据库中。我个人建议只存储路径。如果文件非常大,您肯定不想将其放在数据库中。

现在,当您下次运行上面的脚本时,首先在数据库中检查标识符,并提取时间戳。如果当前时间和存储的时间戳之间的差异大于5分钟,则从URL提取并更新数据库。否则,从数据库加载文件。
如果您没有数据库设置,您可以只使用文件来做同样的事情,其中一个文件或文件中的字段将包含您上次下载文件时的时间戳。

mwngjboj

mwngjboj5#

首先,您可能需要检查设计模式: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)
zujrkrfu

zujrkrfu6#

最佳做法

$cacheKey=md5_file('file.php');
djp7away

djp7away7#

您可以在第一次点击时保存文件的副本,然后使用filemtime检查后续点击时本地文件最后一次修改的时间戳。

vcudknz3

vcudknz38#

你可以把它扭曲成一个类似缓存的方法:

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

siv3szwd9#

我认为您需要一些(伪代码)逻辑,例如:

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

use $file

相关问题