如何获取SMB远程服务器中文件的创建时间?
解决SMB共享文件创建时间获取及跨机器访问问题
PHP内置的SMB流对文件元数据的支持有限,filemtime/filectime这类函数无法获取SMB服务器上文件的创建时间,以下是几个可行的解决方向:
方案一:调用系统smbclient命令行工具
利用系统自带的smbclient(需提前安装)来获取文件属性,这是最容易实现的方案,无需额外扩展。
示例代码
$cntx = stream_context_create( array( 'smb' => array( 'username' => 'me', 'password' => 'mypass' ) ) ); $dir = 'smb://192.168.100.222/MY_FOLDER$'; if ($lst = opendir($dir, $cntx)) { while (($file = readdir($lst)) !== false) { // 过滤PDF文件(统一转小写避免大小写问题) if (strtolower(substr($file, -3)) === 'pdf') { // 构建smbclient命令,用escapeshellarg防止命令注入 $command = sprintf( 'smbclient //192.168.100.222/MY_FOLDER$ -U %s%%%s -c \'allinfo "%s"\'', escapeshellarg('me'), escapeshellarg('mypass'), escapeshellarg($file) ); // 执行命令并捕获输出 $output = shell_exec($command); // 正则匹配创建时间(输出格式可能因系统版本略有差异,需根据实际调整) if (preg_match('/Creation time:\s+(.*)/', $output, $matches)) { $creationTimestamp = strtotime($matches[1]); $creationTime = date('Y-m-d H:i:s', $creationTimestamp); // 这里添加和本地文件对比的逻辑 echo "文件 {$file} 的创建时间:{$creationTime}\n"; } } } closedir($lst); }
注意:确保服务器已安装smbclient,且PHP进程有执行系统命令的权限;必须用escapeshellarg转义参数,避免命令注入风险。
方案二:使用第三方PHP SMB库
借助专门的SMB库来实现完整的协议交互,这类库原生支持文件元数据获取,无需依赖系统命令。
示例(基于php-smbclient扩展)
- 先安装扩展:
pecl install smbclient - 代码实现:
$smb = new SmbClient(); // 连接SMB服务器 $smb->connect('192.168.100.222', 'me', 'mypass'); // 切换到目标共享目录 $smb->chdir('MY_FOLDER$'); // 获取目录下所有文件信息 $files = $smb->dir('.', SMBCLIENT_DIR_ALL); foreach ($files as $file) { if (strtolower(substr($file['name'], -3)) === 'pdf') { // 直接获取创建时间戳 $creationTimestamp = $file['creation_time']; $creationTime = date('Y-m-d H:i:s', $creationTimestamp); // 本地文件对比逻辑 echo "文件 {$file['name']} 的创建时间:{$creationTime}\n"; } } // 断开连接 $smb->disconnect();
如果不想编译扩展,也可以选择纯PHP实现的SMB库,不过性能和稳定性略逊于C扩展。
方案三:挂载SMB共享到本地文件系统
将SMB共享挂载到服务器本地目录,之后就可以像操作本地文件一样使用stat()等函数获取元数据,适合长期稳定访问的场景。
操作步骤
- Linux系统下挂载共享(需安装
cifs-utils):
mount -t cifs //192.168.100.222/MY_FOLDER$ /mnt/smb_share -o username=me,password=mypass
- PHP中直接操作挂载目录:
$dir = '/mnt/smb_share'; if ($lst = opendir($dir)) { while (($file = readdir($lst)) !== false) { if (strtolower(substr($file, -3)) === 'pdf') { $filePath = rtrim($dir, '/') . '/' . $file; // 获取文件状态信息 $stat = stat($filePath); // Linux下birthtime是文件创建时间,若不存在则 fallback 到ctime $creationTimestamp = $stat['birthtime'] ?? $stat['ctime']; $creationTime = date('Y-m-d H:i:s', $creationTimestamp); // 本地文件对比逻辑 echo "文件 {$file} 的创建时间:{$creationTime}\n"; } } closedir($lst); }
跨机器访问处理:上述所有方案,只需替换SMB服务器地址、共享目录名、认证信息,即可直接访问另一台机器的SMB共享,逻辑完全复用。
内容的提问来源于stack exchange,提问作者Rogério Marques
相关产品推荐
相关产品推荐

