You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js搭建HTTP服务页面链接显示但无法正常点击跳转

问题原因
  • 核心原因:你生成的a标签用了file:///开头的本地文件协议链接。现代浏览器有强制安全策略,禁止从HTTP/HTTPS加载的页面直接跳转/加载本地file协议资源,防止恶意网站随意读取用户本地文件。你手动复制链接粘贴到地址栏能打开,是因为这个操作是用户主动触发的,不受该安全策略限制。
  • 附带的代码bug:
    • 表格闭合标签拼写错误:开标签是<table>,结束标签错写成</tables>,会导致HTML结构解析异常
    • 日志路径前后不一致:读取日志列表用的路径是G:/logs/,拼接链接时写的是G:/NodeOctaveService/logs/,路径不匹配会导致后续找不到文件
    • fs.readdirSync是同步API,不需要传入回调函数,传入的回调不会生效,出错时会直接抛出异常
    • 现有服务仅处理了根路径的HTML返回,没有配置日志文件的请求路由,就算把链接改成相对路径,点击后也会返回404
    • h1标签错误写在了head标签内,不符合HTML规范
    • 响应头未指定字符集,容易出现中文乱码
修复方案

把链接改成服务端相对路径,同时给服务端加日志文件的路由处理逻辑,让服务端动态返回请求的日志内容即可,修复后的完整代码如下:

/*
------------------------------------------------
------------------------------------------------
<<<<<<<<<<<<< Below created by J.E >>>>>>>>>>>>>
------------------------------------------------
------------------------------------------------
*/

/* requires */
var fs = require('fs')
const http = require("http");
const path = require('path'); // 引入path处理路径拼接,规避跨平台路径问题

/*----------------------
 setting up the server 
 ----------------------*/
const host = 'localhost';
const port = 8080;
// 统一日志目录配置,避免前后路径不一致
const logdirname = "G:/logs/";

// 服务启动时读取一次日志列表即可,无需每次请求重复读取
let all_logs = [];
try {
  all_logs = fs.readdirSync(logdirname);
} catch (err) {
  console.error('读取日志目录失败:', err);
}

let link = "<table>";
all_logs.forEach((log_, i) => {
  // 替换file协议链接为服务端相对路径,对文件名做编码处理特殊字符
  link += `<tr><td><a href="/logs/${encodeURIComponent(log_)}">Log File ${i}</a></td></tr>`;
})
// 修正表格闭合标签拼写错误
link += "</table>";

http.createServer(function (req, res) {
  // 路由判断:匹配日志文件请求
  if (req.url.startsWith('/logs/')) {
    // 提取请求的日志文件名,做安全校验防止路径穿越攻击
    const logFileName = decodeURIComponent(req.url.replace('/logs/', ''));
    const logFilePath = path.join(logdirname, logFileName);
    // 拦截恶意构造的跨目录路径请求,避免服务器其他文件被非法读取
    if (!logFilePath.startsWith(path.resolve(logdirname))) {
      res.writeHead(403);
      res.end('Forbidden');
      return;
    }
    // 读取目标日志文件返回
    fs.readFile(logFilePath, (err, data) => {
      if (err) {
        res.writeHead(404);
        res.end('Log file not found');
        return;
      }
      res.writeHead(200, {
        'Content-Type': 'text/plain; charset=utf-8' // 指定纯文本类型和编码,避免乱码
      });
      res.end(data);
    })
    return;
  }

  // 根路径返回日志列表首页
  var html = buildHtml();
  res.writeHead(200, {
    'Content-Type': 'text/html; charset=utf-8' // 加字符集配置避免页面中文乱码
  });
  res.end(html);
}).listen(port);

console.log(`Server is running on http://${host}:${port}`);

/*------------------------
  生成首页HTML
------------------------*/
function buildHtml(){
  var header = `
  <title>Octave Service Links</title>
<style>
      *,
      html{
          margin: 0;
          padding: 0;
          border: 10;
          border-color: blueviolet;
      }

      html{
          width: 100%;
          height: 100%;
      }

      body{
          width: 100%;
          height: 100%;
          position: relative;
          background-color:lightgoldenrodyellow;
      }

      .center{
          width: 100%;
          height: 50%;
          margin: 0;
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          color:darkgreen;
          font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
          text-align: center;
      }

      h1{
      font-size: 80px;
      color: blueviolet;
      }
      </style>
      `;
  // 将h1移到body内,符合HTML规范
  var body = `
  <h1> Click the link to the log file you want to open. </h1>
  ${link} 
  `;

  return "<!DOCTYPE html>" + "<html><head>" + header + "</head><body>" + body + "</body></html>";
}

内容的提问来源于stack exchange,提问作者James_Calvert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 02:46:12