PHP Conference Japan 2024

filemtime

(PHP 4, PHP 5, PHP 7, PHP 8)

filemtime获取文件修改时间

描述

filemtime(string $filename): int|false

此函数返回文件数据块被写入的时间,即文件内容被更改的时间。

参数

filename

文件的路径。

返回值

返回文件上次修改的时间,如果失败则返回 false。时间以 Unix 时间戳返回,适合 date() 函数。

错误/异常

失败时,会发出 E_WARNING

示例

示例 #1 filemtime() 示例

<?php
// 输出例如 somefile.txt 最后修改时间:2002年12月29日 22:16:23。

$filename = 'somefile.txt';
if (
file_exists($filename)) {
echo
"$filename was last modified: " . date ("F d Y H:i:s.", filemtime($filename));
}
?>

注释

注意:

请注意,不同文件系统的時間分辨率可能有所不同。

注意: 此函数的结果会被缓存。有关详细信息,请参阅 clearstatcache()

提示

从 PHP 5.0.0 开始,此函数也可以与某些 URL 封装器一起使用。请参考 支持的协议和封装器 以确定哪些封装器支持 stat() 函数族。

参见

  • filectime() - 获取文件的 inode 更改时间
  • stat() - 提供有关文件的信息
  • touch() - 设置文件的访问和修改时间
  • getlastmod() - 获取页面上次修改的时间

添加注释

用户贡献的注释 30 条注释

geekman dot info 的 geeks
16 年前
这是一个非常方便的函数,用于处理浏览器缓存。例如,假设您有一个样式表,并且您希望确保每个人都拥有最新版本。您可以每次编辑时都重命名它,但这会很麻烦。相反,您可以这样做

<?php
echo '<link rel="stylesheet" type="text/css" href="style.css?' . filemtime('style.css') . '" />';
?>

示例输出

<link rel="stylesheet" type="text/css" href="style.css?1203291283" />

通过将 GET 值(UNIX 时间戳)附加到样式表 URL,您可以使浏览器认为样式表是动态的,因此它会在修改日期更改时重新加载样式表。
dds dot nl 的 paranoid
21 年前
要获取目录的上次修改时间,您可以使用此方法

<pre>
$getLastModDir = filemtime("/path/to/directory/.");
</pre>

请注意最后的点,这是将目录视为文件并实际获取其上次修改日期所必需的。

当您只想在网站首页显示一条“上次更新”消息,并且仍然考虑网站的所有文件时,这将非常有用。

此致,
Frank Keijzers
yahoo dot com 的 habazi
19 年前
“这并不(一定)正确,目录的修改时间将是目录中(而不是其子目录中)最后一个文件*创建*的时间。”

这也不一定正确。在 *nix 系统中,时间戳可以独立设置。例如,“touch directory”命令会更新目录的时间戳,而无需创建文件。

此外,删除文件也会更新目录的时间戳。
gmail dot com 的 solarijj
17 年前
要获取某些远程文件的修改日期,您可以使用 codewalker dot com 的 notepad 编写的优秀函数(由 web dot de 的 dma05 和 lillesvin dot net 的 madsen 改进)。

但是现在您可以使用 stream_get_meta_data (PHP>4.3.0) 更轻松地实现相同的结果。

但是,如果发生某些重定向,则可能会出现问题。在这种情况下,服务器 HTTP 响应不包含 Last-Modified 标头,但包含一个 Location 标头,指示文件的位置。下面的函数处理任何重定向,甚至多个重定向,以便您可以访问您想要获取其上次修改日期的实际文件。

此致,
JJS。

<?php

// 获取远程文件最后修改日期 (返回 Unix 时间戳)
function GetRemoteLastModified( $uri )
{
// 默认值
$unixtime = 0;

$fp = fopen( $uri, "r" );
if( !
$fp ) {return;}

$MetaData = stream_get_meta_data( $fp );

foreach(
$MetaData['wrapper_data'] as $response )
{
// 情况:重定向
if( substr( strtolower($response), 0, 10 ) == 'location: ' )
{
$newUri = substr( $response, 10 );
fclose( $fp );
return
GetRemoteLastModified( $newUri );
}
// 情况:最后修改时间
elseif( substr( strtolower($response), 0, 15 ) == 'last-modified: ' )
{
$unixtime = strtotime( substr($response, 15) );
break;
}
}
fclose( $fp );
return
$unixtime;
}
?>
MarkAgius (markagius at markagius dot co dot uk)
3年前
filemtime(..) 仅适用于服务器上的文件。
$T=filesize("index.php"); // 可行。
$T=filesize("/public_html/dir/index.php"); // 可行。

但以下方法不可行。
$T=filesize("https://mydomain.com/dir/index.php"); // 不可行,相同域名但使用网址。
$T=filesize("https://otherdomain.com/dir/index.php"); // 其他域名,不可行。

要获取其他网站的文件日期,请尝试
(注意:时区可能为格林威治标准时间 (GMT),而不是您的本地时区)

$T = getFileDate("https://mydomain.com/dir/index.php");
$T = getFileDate("https://otherdomain.com/dir/index.php");

function getFileDate($filePath){
// 与 filemtime(..) 相同,但也可用于远程文件。
// 例如:print date("j/m/Y, g:i:sa (e)",getFileDate("https://abc.com/file.jpg"));
// 文件未找到,则返回 -307756800 (1960年4月1日)
$ret = -(3562 *24*60*60); // 1960年4月1日 3562 = 1970年1月1日之前的秒数

$ch = curl_init($filePath);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 尝试获取文件的修改日期。
curl_setopt($ch, CURLOPT_FILETIME, true);
$result = curl_exec($ch);
if($result===false){
die(curl_error($ch));
return $ret;
}

$ret = curl_getinfo($ch, CURLINFO_FILETIME);
curl_close($ch);

return $ret;
}
erelsgl (erelsgl at gmail dot com)
14年前
更简便粗略的缓存代码

<?php
$cache_file
= '缓存文件URI';
$cache_life = '120'; // 缓存时间,单位秒

$filemtime = @filemtime($cache_file); // 如果文件不存在,则返回 FALSE
if (!$filemtime or (time() - $filemtime >= $cache_life)){
ob_start();
resource_consuming_function();
file_put_contents($cache_file,ob_get_flush());
}else{
readfile($cache_file);
}
?>
myselfasunder (myselfasunder at gmail dot XYZ dot com)
14年前
由于 `filemtime()` 在 Windows 下调用 Windows 的 `stat()` 函数,而 `stat()` 函数实现了夏令时 (根据此错误:http://bugs.php.net/bug.php?id=40568),因此存在一个深层问题。文件时间的夏令时检测会因当前系统当前时间是否处于夏令时而混乱。

这是针对所有恼人错误的修复方法

<?php
function GetCorrectMTime($filePath)
{

$time = filemtime($filePath);

$isDST = (date('I', $time) == 1);
$systemDST = (date('I') == 1);

$adjustment = 0;

if(
$isDST == false && $systemDST == true)
$adjustment = 3600;

else if(
$isDST == true && $systemDST == false)
$adjustment = -3600;

else
$adjustment = 0;

return (
$time + $adjustment);
}
?>

Dustin Oprea
匿名用户
19 年前
下面的评论指出

"使用此函数获取目录的修改日期时,"
"它返回该目录中最后修改的文件的日期。"

这并不总是正确的,目录的修改时间将是目录中(而不是其子目录中)最后创建文件的创建时间。
adam (adam at roomvoter dot com)
20年前
前面允许您删除所有超过两周旧的文件的代码片段使用了函数 (filemtime) - 它检查文件的原始创建时间(与文件系统无关)。您可能需要使用 filectime() - 它查看文件在您的文件系统上最后更改的时间。

if (is_dir("$path") )
{
$handle=opendir($path);
while (false!==($file = readdir($handle))) {
if ($file != "." && $file != "..") {
$Diff = (time() - filectime("$path/$file"))/60/60/24;
if ($Diff > 14) unlink("$path/$file");

}
}
closedir($handle);
}
_michael
14年前
在 Windows 上测试时,我注意到 filemtime 的精度只有 1 秒。

因此,如果您使用 clearstatcache()filemtime() 检查文件是否已修改,则可能无法检测到更改。修改必须在不到一秒钟内完成。

(我在 Windows XP 上使用 Apache 时遇到了这个问题。)
notepad (notepad at codewalkers dot com)
19 年前
我需要能够获取远程站点上图像的修改时间。以下是借助 Joe Ferris 的解决方案。

<?php

function filemtime_remote($uri)
{
$uri = parse_url($uri);
$handle = @fsockopen($uri['host'],80);
if(!
$handle)
return
0;

fputs($handle,"GET $uri[path] HTTP/1.1\r\nHost: $uri[host]\r\n\r\n");
$result = 0;
while(!
feof($handle))
{
$line = fgets($handle,1024);
if(!
trim($line))
break;

$col = strpos($line,':');
if(
$col !== false)
{
$header = trim(substr($line,0,$col));
$value = trim(substr($line,$col+1));
if(
strtolower($header) == 'last-modified')
{
$result = strtotime($value);
break;
}
}
}
fclose($handle);
return
$result;
}
// echo filemtime_remote('http://www.somesite.com/someimage.jpg');

?>
wookie at at no-way dot org
21 年前
另一个方便的小工具;用于获取目录中文件的最后修改时间。如果将 $doRecursive 参数设置为 true,它甚至可以递归处理目录。基于我在本网站上看到的某个文件/目录列表函数。 ;)

function mostRecentModifiedFileTime($dirName,$doRecursive) {
$d = dir($dirName);
$lastModified = 0;
while($entry = $d->read()) {
if ($entry != "." && $entry != "..") {
if (!is_dir($dirName."/".$entry)) {
$currentModified = filemtime($dirName."/".$entry);
} else if ($doRecursive && is_dir($dirName."/".$entry)) {
$currentModified = mostRecentModifiedFileTime($dirName."/".$entry,true);
}
if ($currentModified > $lastModified){
$lastModified = $currentModified;
}
}
}
$d->close();
return $lastModified;
}
Will Davies Vasconcelos
13年前
这是一个方便的脚本,用于创建一个csv文件,其中包含文件名以及给定文件夹中文件的插入日期

<?php
header
("Pragma: public");
header("Cache-Control: private");
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=age-of-files.csv");

$result = array();
$handle = opendir(".");
while (
$datei = readdir($handle))
{
if ((
$datei != '.') && ($datei != '..'))
{
$file = "./".$datei;
if (!
is_dir($file))
$result[] = $file;
}
}
closedir($handle);
foreach(
$result as $r)
if (
file_exists($r))
echo
substr($r,2).",".date ("m/d/Y", filemtime($r))."\r\n";
?>
Benan Tumkaya (benantumkaya at yahoo)
18年前
这是一个小的但方便的脚本,您可以使用它来查找服务器中哪些文件在您指定的日期/时间之后被修改。此脚本将递归遍历指定目录中的所有文件夹,并回显修改后的文件及其最后修改日期/时间……

// 从这里开始
// 在此处输入要搜索的目录。如果要搜索整个域,请输入 /
$dir='/';

// 以 YYYY-mm-dd hh:mm:ss 的格式输入要比较的日期
$comparedatestr="2006-08-12 00:00:00";
$comparedate=strtotime($comparedatestr);

// 我在这里运行函数以开始搜索。
directory_tree($dir,$comparedate);

// 这是执行搜索的函数……
function directory_tree($address,$comparedate){

@$dir = opendir($address);

if(!$dir){ return 0; }
while($entry = readdir($dir)){
if(is_dir("$address/$entry") && ($entry != ".." && $entry != ".")){
directory_tree("$address/$entry",$comparedate);
}
else {

if($entry != ".." && $entry != ".") {

$fulldir=$address.'/'.$entry;
$last_modified = filemtime($fulldir);
$last_modified_str= date("Y-m-d h:i:s", $last_modified);

if($comparedate < $last_modified) {
echo $fulldir.'=>'.$last_modified_str;
echo "<BR>";
}

}

}

}

}
nieprzeklinaj at gmail dot com
11年前
这是一个方便的小函数,用于智能缓存覆盖 :)
<?php
function img($src, $alt='', $attr='')
{
if(
file_exists($src))
{
$lmod = filemtime($src);
echo
'<img src="'.$src.'?lmod='.$lmod.'" alt="'.$alt.'" '.$attr.' />';
}
}
?>
jay at fudge dot org
25年前
如果您需要在父网页上实现此功能,则应使用 getlastmod()
例如:
<?php echo "Last modified: ".date( "F d Y H:i:s.", getlastmod() ); ?>
包含在页面中……例如,作为所有页面的公共页脚包含
Anonymous
15年前
请注意,下面许多人提供的用于获取目录中特定时间之后修改的文件的函数在 Windows 操作系统上无法获取所有文件。

如果您复制并粘贴文件夹内或从另一个文件夹复制到文件夹中的任何文件(例如可能使用但不会立即修改的图像),则这些复制文件的修改时间不会更新,只有创建时间会更新。

您需要将 filectime 与 filemtime 一起使用,以确保获取未修改但显然是新文件的复制文件。
Don
9年前
查找目录中最旧的文件
$directory= "C:\\";

$smallest_time=INF;

$oldest_file='';

if ($handle = opendir($directory)) {

while (false !== ($file = readdir($handle))) {

$time=filemtime($directory.'/'.$file);

if (is_file($directory.'/'.$file)) {

if ($time < $smallest_time) {
$oldest_file = $file;
$smallest_time = $time;
}
}
}
closedir($handle);
}

echo $oldest_file;
csnyder at chxo dot com
18年前
如果您的系统上 PHP 的整数类型只有 32 位,则对于大于 2GB 的文件,filemtime() 将失败,并显示警告“stat failed”。所有与 stat() 相关的命令都将表现出相同的行为。

作为解决方法,您可以调用系统的 stat 命令来获取文件的修改时间

在 FreeBSD 上
$mtime = exec ('stat -f %m '. escapeshellarg ($path));

在 Linux 上
$mtime = exec ('stat -c %Y '. escapeshellarg ($path));

感谢“mpb dot mail at gmail dot com”对 stat() 的类似评论。
info at daniel-marschall dot de
15年前
确定目录中最新文件的 timestamps 可能很有用。(例如,如果您想知道项目上次更改的时间)。

以下函数将帮助您

<?php

function getAllFiles($directory, $recursive = true) {
$result = array();
$handle = opendir($directory);
while (
$datei = readdir($handle))
{
if ((
$datei != '.') && ($datei != '..'))
{
$file = $directory.$datei;
if (
is_dir($file)) {
if (
$recursive) {
$result = array_merge($result, getAllFiles($file.'/'));
}
} else {
$result[] = $file;
}
}
}
closedir($handle);
return
$result;
}

function
getHighestFileTimestamp($directory, $recursive = true) {
$allFiles = getAllFiles($directory, $recursive);
$highestKnown = 0;
foreach (
$allFiles as $val) {
$currentValue = filemtime($val);
if (
$currentValue > $highestKnown) $highestKnown = $currentValue;
}
return
$highestKnown;
}

// 使用示例

echo '最新文件的時間戳記:<br>';
echo
date('Y-m-d H:i:s', getHighestFileTimestamp('../'));

?>
dma05 at web dot de
19 年前
关于 "notepad at codewalkers dot com" 的代码

这段代码非常简洁,但我只想指出,在 HTTP 请求中使用 "HEAD" 方法而不是 "GET" 方法可能更好,因为这样就不会下载整个资源……

http/1.1 定义片段
"9.4 HEAD" 部分

HEAD 方法与 GET 方法相同,只是服务器在响应中_必须_不返回消息体。对 HEAD 请求的响应中 HTTP 头包含的元信息_应该_与对 GET 请求的响应中发送的信息相同。此方法可用于获取请求隐含实体的元信息,而无需传输实体体本身。此方法常用于测试超文本链接的有效性、可访问性和最近的修改。[...]
--- 片段结束 ---

代码将是……

--- 片段 ---
fputs($handle,"HEAD $uri[path] HTTP/1.1\r\nHost: $uri[host]\r\n\r\n");
--- 片段结束 ---

此致,Magnus
contacto at hardcode dot com dot ar
15年前
在处理 SWF 文件(Flash 动画)时,有一种很好的方法可以避免浏览器缓存。我过去一直手动执行此操作,然后使用随机数,但对于大型在线动画,这会变得很烦人,因为服务器总是下载整个动画,即使没有更改。
但是……

这将奏效

base.swf?rand=<?php echo filemtime("base.swf") ?>

<embed src="base.swf?rand=<?php echo filemtime("base.swf") ?>" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="1680" height="1050">
tobias
11年前
提到的示例

$filename = 'somefile.txt';
if (file_exists($filename)) {
echo "$filename 最后修改时间: " . date ("F d Y H:i:s.", filemtime($filename));
}

有效,但是从通过 PHP 提供静态文件的性能角度来看并不理想,因为它基本上需要执行两次文件系统操作(file_exists 和 filemtime)。更有效的方法是仅使用 filemtime,并使用以下方法节省 file_exists 的开销

$filename = 'somefile.txt';
$fmtime = filemtime($filename);
if (!$fmtime) {
echo "$filename 最后修改时间: " . date ("F d Y H:i:s.", $fmtime);
}
gerardj at home dot com
25年前
如果您将其放在要添加日期戳的每个页面上,则上述代码可以正常工作。我发现,如果您在包含或引用的文件中放置 filemtime(__FILE__) 之类的引用,则将返回继承文件的修改时间,而不是执行继承的文件的时间。
Steve GS
4年前
如果文件不在执行脚本所在的同一目录中,除非您使用 $_SERVER,否则将导致失败。这是因为,与 file_exists() 一样,该命令作用于文件系统,而不是通过 HTTP。因此,这将无法正常工作(并且可能会显示警告)

echo '<img src="' . $home_url . '/images/image.jpg?v=' . filemtime ($home_url . '/images/image.jpg') . '" />';

但这将

echo '<img src="' . $home_url . '/images/image.jpg?v=' . filemtime ($_SERVER['DOCUMENT_ROOT'] . '/images/image.jpg') . '" />';

上面的第二个脚本将确保任何更新的图像都能保证替换其前身,而无需强制浏览器在每次访问时都重新加载图像。
arkadia81 at gmail dot com
11年前
对 "tobias" 帖子的一个小修改

代替
$filename = 'somefile.txt';
$fmtime = filemtime($filename);
if (!$fmtime) {
echo "$filename 最后修改时间: " . date ("F d Y H:i:s.", $fmtime);
}

它应该是这样的
$filename = 'somefile.txt';
$fmtime = filemtime($filename);
if ($fmtime != false) {
echo "$filename 最后修改时间: " . date ("F d Y H:i:s.", $fmtime);
}

filemtime() 在失败时返回 false,因此在第一个示例中,它永远不会显示修改日期。
james dot schafer at gotalk dot net dot au
14年前
在 Windows 系统上,filectime() 返回创建时间。要查找更改时间,请使用 fileatime() 或 filemtime()。
Nilo
14年前
一种编写缓存的廉价且简便的方法

<?php
$cache_file
= '缓存文件的 URI';
$cache_life = '120'; // 缓存时间,以秒为单位

if (!file_exists($cache_file) or (time() - filemtime($cache_file) >= $cache_life)){
ob_start();
resource_consuming_function();
file_put_contents($cache_file,ob_get_flush());
}else{
readfile($cache_file);
}
?>
son9ne at gmail dot com
10年前
如果您使用
<?php
$filename
= 'somefile.txt';
$fmtime = filemtime($filename);
if (!
$fmtime) {
echo
"$filename 最后修改时间: " . date ("F d Y H:i:s.", $fmtime);
}
?>

请注意,它会抛出一个警告,如文档中所述。虽然 tobias 为生产环境提出了一个好点子,但在错误报告关闭时,这可以提高您相对于使用 `file_exists` 的性能。但是,如果错误报告已打开并且正在写入日志……情况并非如此。显然,这取决于服务器规格和错误日志的大小。对于大多数情况,仍然理想的是使用 `file_exists` 方法。
dagger80
14年前
同样在 32 位系统上,filemtime() 也不适用于修改时间设置为 2038 年 1 月以后的文件。这是令人恐惧的 unix 秒的 time_t 溢出错误。

在 Windows 上,您可以将系统时间设置为任何任意将来的日期,并且您创建或编辑的任何新文件都将自动更改为该将来的日期。

如果出于某种原因不允许使用 exec,并且您可以通过 Web URL 访问文件(例如 https://127.0.0.1/yourfile.txt),则另一种解决方法是从 HTTP 头(例如 get_headers(url))获取“上次修改”时间,并将其解析为 DateTime 对象。

我已经测试过了,它适用于 2050 年和 3012 年等年份。
To Top