Node.js中res.download()如何实现不区分大小写的文件名匹配下载?
Node.js 实现不区分文件名大小写下载的可行方案
你遇到的问题本质是因为 Linux 等大小写敏感的文件系统下,文件名匹配会严格校验大小写,只需在调用res.download前先匹配到目录下对应真实文件名即可。
方案1:原生 Node.js 遍历目录匹配(无第三方依赖)
适合存储文件数量较少的目录,无需引入额外依赖:
const fs = require('fs/promises'); const path = require('path'); // 第一步:路径安全校验,防止路径穿越漏洞 const safeInputName = path.basename(fileNameOnly); const targetDir = path.resolve(filePath); // 你的文件存储根目录 try { // 读取目标目录下所有文件 const dirFiles = await fs.readdir(targetDir); // 大小写不敏感匹配真实文件名 const realFileName = dirFiles.find(file => file.toLowerCase() === safeInputName.toLowerCase() ); if (!realFileName) { return res.status(404).send({message: '请求的文件不存在'}); } // 匹配到真实文件后执行下载逻辑 const fullFilePath = path.join(targetDir, realFileName); res.set("Content-Disposition", "inline; filename=" + safeInputName); res.set("Content-Type", "application/pdf"); res.download(fullFilePath, safeInputName, (err) => { if(err) { console.log('Impex Ctlr: There was an error in downloading document: ' + err); res.status(500).send({message: 'Download Error' + err}) } }); } catch (readErr) { console.log('读取目录失败:', readErr); res.status(500).send({message: '服务器内部错误'}); }
方案2:使用 glob 库匹配(适合大文件目录)
如果目录下存储文件数量较多,用 glob 库的匹配能力性能更优:
- 先安装依赖:
npm i glob - 代码示例:
const glob = require('glob'); const path = require('path'); const safeInputName = path.basename(fileNameOnly); const targetDir = path.resolve(filePath); // nocase参数开启大小写不敏感匹配 glob(`${targetDir}/${safeInputName}`, { nocase: true }, (err, matchedFiles) => { if (err) { return res.status(500).send({message: '匹配文件失败'}); } if (matchedFiles.length === 0) { return res.status(404).send({message: '请求的文件不存在'}); } // 取第一个匹配到的文件,可根据业务调整优先级 const fullFilePath = matchedFiles[0]; res.set("Content-Disposition", "inline; filename=" + safeInputName); res.set("Content-Type", "application/pdf"); res.download(fullFilePath, safeInputName, (err) => { if(err) { console.log('Impex Ctlr: There was an error in downloading document: ' + err); res.status(500).send({message: 'Download Error' + err}) } }); });
注意事项
- 必须做路径安全校验,用
path.basename处理传入的文件名,防止攻击者传入../../xxx.js之类的路径穿越 payload 读取服务器敏感文件 - 如果目录下存在多个仅大小写不同的同名文件(如
Test.pdf和test.pdf同时存在),需根据业务需求决定返回优先级,可选择返回修改时间最新的文件,或直接返回400提示文件名存在歧义
内容的提问来源于stack exchange,提问作者hemant
相关产品推荐
相关产品推荐

