如何基于Node.js+MySQL服务端实现动态查询并下载用户对应文件
问题原因
你下载得到.html格式的无效文件,本质是<a>标签的资源路径错误,express找不到对应静态资源时返回了404错误页面(HTML格式),最终被你当成目标文件下载。
解决步骤
步骤1:修正动态页面路由配置
首先确保user.js路由文件中,viewall接口对应的路由配置携带id参数,否则req.params.id无法正常取值:
// user.js 路由 router.get('/view-crew/:id', userController.viewall);
步骤2:修正模板文件的资源路径
你的项目将upload目录配置为静态资源目录,文件访问路径直接以/开头即可。之前的相对路径会和当前页面路由/view-crew/xxx拼接,导致资源路径错误。修改view-crew.hbs中的代码:
{{#each rows}} {{#if this.profile_image}} <!-- 路径前加/表示根路径,同时download属性指定文件名避免后缀识别错误 --> <a href="/{{this.profile_image}}" download="{{this.profile_image}}"> <img class="card__image" src="/{{this.profile_image}}" loading="lazy" alt="User Profile"> {{else}} <img class="card__image" src="/img/cert.png" loading="lazy" alt="User Profile"> </a> {{/if}} {{/each}}
步骤3(可选,更稳定):单独实现文件下载接口
如果需要做权限校验、或者避免静态资源路径泄露,可单独编写下载接口,替代直接访问静态资源:
- 首先在
userController.js中新增下载接口:
const path = require('path'); exports.downloadFile = (req, res) => { connection.query('SELECT profile_image FROM user WHERE id=?', [req.params.id], (err, rows) => { if (err) { console.log(err); return res.status(500).send('服务器错误'); } const fileName = rows[0]?.profile_image; if (!fileName) { return res.status(404).send('用户未上传文件'); } // 此处路径需根据你的controller实际存放位置调整,保证能定位到upload目录 const filePath = path.join(__dirname, '../upload', fileName); res.download(filePath, fileName, (err) => { if (err) { res.status(404).send('文件不存在'); } }); }); };
- 在
user.js中新增下载路由:
router.get('/download/:id', userController.downloadFile);
- 模板中的下载链接改为调用该接口:
<a href="/download/{{this.id}}" download>
额外优化点
你当前的上传逻辑仍然写死了更新id=179的用户数据,建议改为从登录态(cookie/session)中获取当前用户id,动态更新对应用户的profile_image字段,否则其他用户上传的文件都会绑定到id=179的账号上,无法正常查询下载。
内容的提问来源于stack exchange,提问作者Cesare Mannino
相关产品推荐
相关产品推荐

