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

Express中如何传递服务端文件列表渲染index.pug模板并在浏览器展示

问题解决方案

核心问题说明

  • 你当前将GET /路由同时承担了两个职责:渲染pug页面、给前端fetch返回JSON数据,逻辑冲突,前端请求时拿到的是渲染后的HTML而非预期的JSON,会触发解析报错
  • res.render第二个参数必须是键值对格式的对象,直接传入files数组,模板和前端都无法读取到正确的变量
  • 注意你代码中路径拼写可能存在错误:./public/upploads大概率是./public/uploads,还有文件返回路径缺少uploads前缀,前端无法正常加载音频

方案1:拆分路由(适配你现有前端fetch逻辑,改动最小)

1. 修改后端路由代码

// 原有路由只负责渲染首页
router.get('/', (req, res) => {
  res.render('index');
});

// 新增接口路由专门返回录音列表数据
router.get('/api/recordings', (req, res) => {
  // 注意修正路径拼写错误
  let files = fs.readdirSync('./public/uploads');
  console.log(__dirname + " files length  " + files.length);
  files = files.filter((file) => {
    // check that the files are audio files
    const fileNameArr = file.split('.');
    return fileNameArr[fileNameArr.length - 1] === 'mp3';
    // 补全静态资源访问前缀,public下的文件可以直接通过/xxx访问
  }).map((file) => `/uploads/${file}`);
  res.json({ success: true, files });
});

2. 修改前端fetch请求地址

修改listrecordings.js里的请求路径,同时补充容器元素获取逻辑:

function fetchRecordings() {
  // 替换为新的接口地址
  fetch('/api/recordings')
    .then((response) => response.json())
    .then((response) => {
      console.log("response " + response);
      if (response.success && response.files) {
        // 补充获取容器元素的逻辑
        const recordingsContainer = document.getElementById('recordings');
        //remove all previous recordings shown
        recordingsContainer.innerHTML = '';
        response.files.forEach((file) => {
          //create the recording element
          const recordingElement = createRecordingElement(file);
          //add it the the recordings container
          recordingsContainer.appendChild(recordingElement);
        })
      }
    })
    .catch((err) => console.error(err));
};
// 页面加载完成后自动执行拉取列表
document.addEventListener('DOMContentLoaded', fetchRecordings);

方案2:服务端直接注入数据(无需额外fetch请求)

如果你不想新增接口,可以直接在渲染pug的时候把文件列表注入到页面中:

1. 修改后端路由传参

router.get('/', (req, res) => {
  let files = fs.readdirSync('./public/uploads');
  console.log(__dirname + " files length  " + files.length);
  files = files.filter((file) => {
    const fileNameArr = file.split('.');
    return fileNameArr[fileNameArr.length - 1] === 'mp3';
  }).map((file) => `/uploads/${file}`);
  // 以对象格式传入参数,key为模板中可读取的变量名
  res.render('index', { files });
});

2. 修改index.pug模板

extends layout
block content 
  h1= 'saved files' 
  #recordings.recordings.row
    // 可选:服务端直接渲染列表,无需前端JS操作
    each file in files
      .audio-item
        audio(controls src=file)
  // 把文件列表注入到全局变量,给前端JS使用
  script.
    window.recordingFiles = !{JSON.stringify(files)}
  script(src='/javascripts/listrecordings.js')

3. 修改前端JS,直接使用注入的变量

function renderRecordings() {
  const recordingsContainer = document.getElementById('recordings');
  recordingsContainer.innerHTML = '';
  window.recordingFiles.forEach((file) => {
    const recordingElement = createRecordingElement(file);
    recordingsContainer.appendChild(recordingElement);
  })
}
document.addEventListener('DOMContentLoaded', renderRecordings);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 18:09:03