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
相关产品推荐
相关产品推荐

