const express = require('express'); const router = express.Router(); const fs = require('fs').promises; const { getActualLogPath } = require('../utils/file-utils'); // 读取目录内容 router.get('/readdir', async (req, res) => { try { const dirPath = req.query.path; if (!dirPath) { return res.status(400).json({ error: '缺少路径参数' }); } // 获取实际的文件系统路径 const actualPath = await getActualLogPath(dirPath); // 安全检查 if (!actualPath) { return res.status(403).json({ error: '无权访问该目录' }); } // 检查目录是否存在 try { const stats = await fs.stat(actualPath); if (!stats.isDirectory()) { return res.status(400).json({ error: '指定的路径不是目录' }); } } catch (statError) { // 如果目录不存在但是请求的是/log,尝试创建它 if (statError.code === 'ENOENT' && dirPath === '/log') { try { // 确保XNCore下有log目录 await fs.mkdir(actualPath, { recursive: true }); } catch (mkdirError) { console.error('创建日志目录失败:', mkdirError); return res.status(500).json({ error: '创建日志目录失败' }); } } else { throw statError; } } // 读取目录内容 const files = await fs.readdir(actualPath); // 返回文件列表 res.json({ files }); } catch (error) { console.error('读取目录失败:', error); // 处理特定错误 if (error.code === 'ENOENT') { return res.status(404).json({ error: '目录不存在' }); } if (error.code === 'EACCES') { return res.status(403).json({ error: '没有权限访问目录' }); } res.status(500).json({ error: '读取目录失败', message: error.message }); } }); // 获取文件状态信息 router.get('/stat', async (req, res) => { try { const filePath = req.query.path; if (!filePath) { return res.status(400).json({ error: '缺少路径参数' }); } // 获取实际的文件系统路径 const actualPath = await getActualLogPath(filePath); // 安全检查 if (!actualPath) { return res.status(403).json({ error: '无权访问该文件' }); } // 获取文件状态 const stats = await fs.stat(actualPath); // 返回文件信息 res.json({ size: stats.size, isFile: stats.isFile(), isDirectory: stats.isDirectory(), created: stats.birthtime, modified: stats.mtime, accessed: stats.atime, mtime: stats.mtime.toISOString() }); } catch (error) { console.error('获取文件状态失败:', error); // 处理特定错误 if (error.code === 'ENOENT') { return res.status(404).json({ error: '文件不存在' }); } if (error.code === 'EACCES') { return res.status(403).json({ error: '没有权限访问文件' }); } res.status(500).json({ error: '获取文件状态失败', message: error.message }); } }); // 读取文件内容 router.get('/readFile', async (req, res) => { try { const filePath = req.query.path; if (!filePath) { return res.status(400).json({ error: '缺少路径参数' }); } // 获取实际的文件系统路径 const actualPath = await getActualLogPath(filePath); // 安全检查 if (!actualPath) { return res.status(403).json({ error: '无权访问该文件' }); } // 只允许访问.log文件 if (!actualPath.endsWith('.log')) { return res.status(403).json({ error: '只能访问日志文件' }); } // 获取文件状态 const stats = await fs.stat(actualPath); // 检查文件大小,限制读取过大的文件 const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB if (stats.size > MAX_FILE_SIZE) { return res.status(413).json({ error: '文件过大,无法读取' }); } // 读取文件内容 const content = await fs.readFile(actualPath, 'utf-8'); // 设置响应头 res.setHeader('Content-Type', 'text/plain; charset=utf-8'); // 返回文件内容 res.send(content); } catch (error) { console.error('读取文件内容失败:', error); // 处理特定错误 if (error.code === 'ENOENT') { return res.status(404).json({ error: '文件不存在' }); } if (error.code === 'EACCES') { return res.status(403).json({ error: '没有权限访问文件' }); } res.status(500).json({ error: '读取文件内容失败', message: error.message }); } }); module.exports = router;