
本文介绍如何在 php 中安全、规范地扫描指定目录(如 archives/),筛选符合条件的文件,生成结构化 json 数据,并写入到磁盘文件(如 archives/events.txt)中,同时规避常见错误(如未定义变量、路径问题、文件覆盖风险等)。
本文介绍如何在 php 中安全、规范地扫描指定目录(如 archives/),筛选符合条件的文件,生成结构化 json 数据,并写入到磁盘文件(如 archives/events.txt)中,同时规避常见错误(如未定义变量、路径问题、文件覆盖风险等)。
在 Web 开发中,动态读取目录内容并持久化为可读文件是一项常见需求。但直接调用 scandir() 并配合 file_put_contents() 时,若缺乏路径校验、文件过滤和错误处理,极易导致脚本失败或数据异常。例如,原始代码中 JavaScript 端 xhr.send(data) 报错 Uncaught ReferenceError: data is not defined,根源在于前端未定义 data 变量,且后端 json-events.php 未做任何输入校验与容错——它无条件执行 scandir('archives'),却未检查目录是否存在、是否可读,也未排除系统隐藏文件(. 和 ..),更未对输出格式做标准化处理(如使用 print_r() 输出的是人类可读文本,而非机器可解析的 JSON)。
以下是推荐的健壮实现方案:
✅ 正确的 PHP 后端逻辑(json-events.php)
<?php
// json-events.php —— 安全、可复用的目录扫描与持久化脚本
function list_contents($dir, $suffix = '.txt') {
// 1. 路径规范化与存在性校验
$dir = rtrim(trim($dir), '/\');
if (!is_dir($dir) || !is_readable($dir)) {
error_log("❌ Directory not found or unreadable: {$dir}");
return false;
}
// 2. 扫描目录,过滤掉 . 和 .. 等无效项
$files = scandir($dir);
$contents = [];
foreach ($files as $file) {
$path = $dir . '/' . $file;
// 排除目录、隐藏文件及目标输出文件自身
if (is_file($path) && $file !== 'events.txt' && $file !== '.' && $file !== '..') {
// 按后缀匹配(区分大小写)
if (strcasecmp(substr($file, -strlen($suffix)), $suffix) === 0) {
// 额外业务规则:仅保留 14 字符长度且以 '2' 开头的文件名(如 20240501-event.txt)
if (strlen($file) === 14 && strpos($file, '2') === 0) {
$contents[] = $file;
}
}
}
}
// 3. 序列化为标准 JSON(非 print_r),确保前端可直接解析
$json = json_encode(array_values($contents), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
if ($json === false) {
error_log('❌ JSON encoding failed: ' . json_last_error_msg());
return false;
}
// 4. 写入目标文件(含路径安全检查)
$outputFile = $dir . '/events.txt';
if (file_put_contents($outputFile, $json) === false) {
error_log("❌ Failed to write to {$outputFile}");
return false;
}
return true;
}
// 执行函数(可按需扩展为 CLI 或 Web 请求入口)
if (php_sapi_name() === 'cli') {
list_contents('archives', '.txt');
} else {
// Web 环境下建议加简单 CSRF 或权限校验(如 session 登录态)
if (list_contents('archives', '.txt')) {
http_response_code(200);
echo json_encode(['status' => 'success', 'file' => 'archives/events.txt']);
} else {
http_response_code(500);
echo json_encode(['status' => 'error', 'message' => 'Failed to generate events list']);
}
}
?>⚠️ 前端调用注意事项(修复原始 JS 错误)
原始 JS 中 xhr.send(data) 的 data 未定义,且未设置请求头。若需通过 AJAX 触发该 PHP 脚本,请确保:
- 使用 POST 时明确发送空数据或必要参数;
- 设置 Content-Type;
- 添加错误处理。
示例修正版:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
立即学习“PHP免费学习笔记(深入)”;
function LISTevents() {
const xhr = new XMLHttpRequest();
xhr.open("POST", "json-events.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onload = function () {
if (xhr.status === 200) {
console.log("✅ Success:", xhr.responseText);
} else {
console.error("❌ Server error:", xhr.status, xhr.statusText);
}
};
xhr.onerror = function () {
console.error("❌ Network error");
};
xhr.send(""); // 发送空体(或传参如 "action=refresh")
return false;
}? 关键总结
- ✅ 永远校验目录路径:使用 realpath() + is_dir() + is_readable();
- ✅ 避免 print_r() 直接写入文件:应使用 json_encode() 生成结构化、可解析的数据;
- ✅ 排除干扰项:显式跳过 .、.. 和输出文件自身(如 events.txt);
- ✅ 增强业务过滤逻辑:如长度、前缀、后缀等,应在 PHP 层完成,而非依赖前端;
- ✅ 添加错误日志与 HTTP 状态码:便于调试与监控;
- ❌ 避免硬编码路径;生产环境建议将目录路径配置化或通过环境变量注入。
运行该脚本后,archives/events.txt 将生成标准 JSON 格式内容,例如:
[ "20240501-log.txt", "20240502-report.txt" ]
既可被浏览器直接加载解析,也可供其他服务程序可靠消费。


















