我有一个非常简单的问题:在PHP中,如果本地版本已经下载超过5分钟,最好的下载文件方式是什么?
在我的实际情况下,我想从远程托管的csv文件获取数据,目前我正在使用:
$file = file_get_contents($url);
没有任何本地副本或缓存。将其转换为缓存版本的最简单方法是什么,其中最终结果不会改变($file保持不变),但如果不久前获取了本地副本,则使用本地副本?
$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);
}
rename()
将其重命名为$cache_file
,这应该是一个原子操作,即$cache_file
要么是旧内容,要么是完整的新内容,绝不会是写了一半的内容。<?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;
这里有一个简单的版本,它还会向远程主机发送一个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);
}
现在,当您下次运行上面的脚本时,请首先检查标识符是否在数据库中,并提取时间戳。如果当前时间与存储的时间戳之间的差异大于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)
最佳实践
$cacheKey=md5_file('file.php');
在第一次访问时,您可以保存文件的副本,然后在后续访问中使用filemtime检查本地文件的最后修改时间戳。
我认为你想要一些(伪代码)逻辑,类似于:
if ($file exists) {
if ($file time stamp older than 5 minutes) {
$file = file_get_contents($url)
}
} else {
$file = file_get_contents($url)
}
use $file
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;
}
$cache_file = $_SERVER['DOCUMENT_ROOT'] . '/my-cache.php';
- farjamPHP_RINIT_FUNCTION
回调中清除了状态缓存,因此它肯定会在每个请求开始时重置。) - Matt Gibson