XNSim/XNSimHtml/routes/filesystem.js
2025-04-28 12:25:20 +08:00

170 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 = getActualLogPath(dirPath);
// 安全检查
if (!actualPath) {
return res.status(403).json({ error: '无权访问该目录' });
}
//console.log('读取目录:', actualPath);
// 检查目录是否存在
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 });
console.log('创建日志目录:', actualPath);
} 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 = getActualLogPath(filePath);
// 安全检查
if (!actualPath) {
return res.status(403).json({ error: '无权访问该文件' });
}
//console.log('获取文件状态:', actualPath);
// 获取文件状态
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 = getActualLogPath(filePath);
// 安全检查
if (!actualPath) {
return res.status(403).json({ error: '无权访问该文件' });
}
// 只允许访问.log文件
if (!actualPath.endsWith('.log')) {
return res.status(403).json({ error: '只能访问日志文件' });
}
//console.log('读取文件:', actualPath);
// 获取文件状态
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;