JS怎样读取服务器文件夹路径,前端如何获取服务器目录路径?

浏览器端的 JavaScript 无法直接读取服务器上的文件夹,真正干活的是 Node.js:用 fs.readdir 拿到目录内容,用 path.join(__dirname, '目标目录') 拼出可靠路径,再把结果通过接口交给前端。 下面按从小白到实战的顺序,把这条链路拆开讲清楚。

浏览器里的 JS 为什么摸不到服务器文件夹

前端 js 能直接读取服务器本地文件夹吗

不能,这是浏览器安全沙箱决定的,你用 <input type="file" webkitdirectory> 选择文件夹,拿到的只是用户主动授权的 FileList,路径还被替换成 C:\fakepath\...,浏览器没有权限、也没有通道去访问服务器的 D:\data\uploads。

2020-0514-Nodejs目录操作与文件操作
加载中
2020-0514-Nodejs目录操作与文件操作
水
水哥澎湃
1633--
原视频地址

行业共识认为,这条边界短期内不会松动,想读服务器目录,只有三种路子:

  • Node.js 后端自己读,比如定时扫目录、生成文件清单。
  • 后端开接口,前端请求 /api/files?dir=xxx 拿列表。
  • 直接把目录挂成静态资源,前端按 URL 访问具体文件。

前两种用得最多,记住一句话:路径字符串是在服务端拼的,浏览器只负责发请求。

Node.js 读取服务器文件夹路径的基本写法

绝对路径、相对路径和 __dirname

先分清三种“起点”:

  • 绝对路径:/var/www/uploads 或 C:\app\data,从盘符或根开始,任何位置都能用。
  • 相对路径:./uploads,起点是当前工作目录(process.cwd()),不是脚本所在目录,很多人在这里栽跟头。
  • __dirname:当前脚本文件所在的绝对目录,CommonJS 里直接可用;ESM 里要用 import.meta.dirname(Node 20.11+)或 fileURLToPath(import.meta.url)。

典型的坑:用 pm2 start app.js 启动,进程工作目录是 /root,fs.readdirSync('./uploads') 就找不到文件了,改成下面这样立刻稳:

const path = require('path');
const fs = require('fs');
const dir = path.join(__dirname, 'uploads');
fs.readdir(dir, (err, files) => {
  if (err) return console.error(err);
  console.log(files);
});

path.join 和 path.resolve 差在哪

两个函数都返回规范化路径,但语义不同:

对比项 path.join path.resolve
行为 按顺序拼接片段并规范化 从右往左拼接,直到拼出绝对路径
遇到绝对路径片段 继续拼接 立刻以该绝对路径为准
起点 不涉及 未生成绝对路径时以 process.cwd() 为底
适用场景 已知父目录,拼子目录 需要得到绝对路径,或处理用户传入路径

日常拼目录用 path.join 就够,结果清晰、没有歧义。path.resolve('a', '/b') 会返回 /b,很多人第一次见会愣一下。

Node.js 读取服务器目录文件列表的完整方法

fs.readdirSync 和 fs.readdir 该选哪个

同步和异步,看你在哪用:

  • readdirSync:脚本、CLI 工具、启动时一次性扫描目录,代码短,直接返回数组。
  • readdir:回调式异步,适合老项目,避免阻塞事件循环。
  • fs.promises.readdir / fs.readdirSync 之外的 await:现代写法,配合 async/await 最舒服。
const { readdir } = require('fs/promises');
async function listDir(dir) {
  const entries = await readdir(dir, { withFileTypes: true });
  return entries.map(e => ({
    name: e.name,
    isDir: e.isDirectory(),
    size: e.isFile() ? require('fs').statSync(require('path').join(dir, e.name)).size : null
  }));
}

关键在 withFileTypes: true,不加这个参数,你只拿到名字,还得逐个 statSync 判断是文件还是文件夹,IO 次数翻倍。

递归读取子目录

readdir 本身不递归,要拿整棵目录树,两条路:

  • fs.readdir(dir, { recursive: true }):Node 20.1+ 支持,一行搞定,返回相对路径数组。
  • 自己写递归:兼容老版本,顺便能控制深度和过滤规则。
function walk(dir, depth = 0, maxDepth = 3) {
  if (depth > maxDepth) return [];
  const items = fs.readdirSync(dir, { withFileTypes: true });
  return items.flatMap(item => {
    const full = path.join(dir, item.name);
    return item.isDirectory() ? walk(full, depth + 1, maxDepth) : [full];
  });
}

加了 maxDepth,是为了防止误扫 node_modules 或系统目录,把进程拖死。

让前端拿到文件夹内容:接口和静态目录

Express 提供文件列表接口

后端读目录,前端发请求,这是最常见的组合,核心是路径校验,不能让用户传什么就读什么。

app.get('/api/files', async (req, res) => {
  const sub = req.query.dir || '';
  const base = path.join(__dirname, 'uploads');
  const target = path.join(base, sub);
  if (!target.startsWith(base + path.sep)) {
    return res.status(403).json({ error: '非法路径' });
  }
  const list = await fs.promises.readdir(target, { withFileTypes: true });
  res.json(list.map(d => d.name));
});

path.join 会自动处理 ,所以必须用 startsWith 做前缀校验,否则 ?dir=../../etc 就能读到服务器任意目录。

静态资源托管的路径配置

如果只是想让前端能下载文件,不必写接口,直接挂静态目录:

app.use('/files', express.static(path.join(__dirname, 'uploads')));

前端访问 /files/report.pdf 即可,注意别把整个项目根目录挂上去,等于把源码和配置全暴露了。

路径处理最容易踩的坑

  • Windows 和 Linux 分隔符不同:写死 'a/b' 在 Windows 上也能跑,但 'a\\b' 到 Linux 就废了,统一用 path.join,它会按平台输出正确分隔符。
  • 中文路径乱码:Node 默认按 UTF-8 处理文件名,Linux 服务器 locale 如果是 C,读出来的中文名可能是乱码,部署时确认 LANG=zh_CN.UTF-8 或 en_US.UTF-8。
  • 权限不足:EACCES 报错不是路径写错了,是运行进程的用户没读权限,查一下 ls -l 的属主。
  • 路径不存在:ENOENT 要单独处理,别让整个服务挂掉,读之前用 fs.existsSync 判断,或直接 try/catch。
  • 符号链接:readdir 不跟随软链,目录软链会被当成文件,需要穿透时加 fs.realpath。
  • ESM 里没有 __dirname:"type": "module" 的项目里,用 import.meta.dirname 或 path.dirname(fileURLToPath(import.meta.url))。

据 Node.js 官方文档说明,fs 模块的所有路径参数都接受 Buffer 和 URL,但传 file:// 开头的 URL 时必须用 url.fileURLToPath 转换,直接传字符串会抛 TypeError。

js 读取服务器文件夹路径的常见问题

为什么我写的相对路径在本地能跑,部署到服务器就报错

因为相对路径的起点是进程工作目录,不是脚本位置,本地你在项目根目录敲 node app.js,工作目录恰好等于项目根目录;线上用 systemd、pm2 或 Docker 启动时,工作目录往往变成 或 /root,解决办法只有一个:涉及读文件的路径,一律用 __dirname 或 path.resolve 锚定,别依赖 。

读取大文件夹时程序卡住或者内存飙升怎么办

readdir 一次性返回整个目录的数组,几十万文件就会吃满内存,换成流式方案:fs.opendir 返回 Dir 对象,可以用 for await...of 逐个拿 Dirent,边读边处理,内存占用稳定在一个文件的量级,同时给递归加深度限制,跳过 .git、node_modules 这类目录,扫描速度能提升明显,业内专家指出,目录遍历的性能瓶颈通常在 stat 调用次数,而不是 readdir 本身,所以能用 withFileTypes 就别额外调 stat。

路径里带空格或者特殊字符会不会出问题

Node 层面对空格、中文、、& 都能正常处理,path.join('a b', 'c d.txt') 没问题,真正出问题的是把路径塞进 URL 或 shell 命令的时候:URL 里要 encodeURIComponent,shell 里要加引号或用 execFile 传数组参数,直接字符串拼接 exec('ls ' + dir),一个文件名带分号就能执行任意命令。

总结一句:浏览器只发请求,Node.js 用 path.join(__dirname, ...) 定路径、用 fs.readdir 读目录,再通过接口或静态托管把结果交给前端。

首发原创文章,作者:王坚‌,如若转载,请注明出处:https://idctop.com/article/785830.html

赞 (0)
上一篇 2026年11月6日 23:13
下一篇 2026年11月6日 23:13

相关推荐

  • ajaxnet怎么插入数据库?ajaxnet连接数据库教程

    在Java开发中,通过JDBC或MyBatis等框架执行SQL语句是实现数据库插入操作的核心方式,其中MyBatis因其配置灵活和易于维护而被广泛采用,数据库插入操作的基础原理数据库插入操作是将新数据记录添加到数据库表中的过程,这一过程涉及多个步骤,包括建立数据库连接、准备SQL语句、执行插入操作以及处理可能的……

    2026年6月5日
    4300
  • 物理机租用真的能拿到硬件吗,物理机租用怎么选

    租用物理机,你拿不到物理硬件,但你可以获得根权限和硬件级控制权,仿佛硬件就在你手中,物理机租用硬件所有权归属所有权与服务商关系物理机租用本质是服务商采购硬件,用户以月或年为单位租用,硬件所有权始终归服务商,用户获得的是硬件资源的独占使用权,行业共识认为,这种模式的优势在于用户无需承担硬件折旧和故障风险,适合追求……

    2026年7月29日
    1300
  • 广州稳定高防ddos服务器怎么选?哪家防御更可靠

    在2026年数字化业务高度依赖实时交互的背景下,部署广州稳定高防ddos服务器是华南及东南亚出海企业保障业务连续性、抵御T级流量洪峰与CC应用层攻击的唯一可靠解,为何华南企业必须锁定广州节点攻防态势的2026年新常态根据国家互联网应急中心CNCERT 2026年一季度通报,华南地区面临的DDoS攻击呈现出短时高……

    2026年4月28日
    6900
  • 越南TotHostVPS测评,2.25美元/月方案实测对比,越南VPS测评

    越南TotHost VPS 2.25美元/月方案实测结论:该方案适合对预算极度敏感且无需高IOPS的轻量级站点或测试环境,但在网络稳定性和SSD性能上存在明显短板,不建议用于生产级核心业务,价格与配置深度解析极致低价背后的硬件真相在2026年的VPS市场中,越南云服务器低价方案已成为许多初创团队和开发者的首选切……

    2026年5月16日
    6000
  • 为什么在QQ里连接服务器失败,是什么原因?

    QQ连接服务器失败,绝大多数情况下是本地网络环境异常、账号安全风控触发或腾讯服务器临时波动导致,并非你的账号被封禁或电脑损坏,你遇到这个问题时,先别急着重装系统,按照下面这些场景逐一排查,大部分都能在几分钟内解决,网络环境问题:最常见的“罪魁祸首”行业共识认为,约七成QQ连接失败案例的根源都在本地网络,当QQ提……

    2026年9月17日
    900
  • Win10邮箱服务器地址怎么设置,邮件服务器怎么填?

    win10邮箱服务器地址在哪设置:快速上手路径在Win10里设置自己的邮箱服务器地址,最直接的方法是打开控制面板里的“邮件”设置,或者在“设置-账户-电子邮件和账户”中添加账户时选择“高级设置”手动输入服务器信息, 按这个入口走,不管你是用Outlook桌面版还是系统自带的邮件应用,都能在同一套逻辑下搞定,下文……

    程序编程 2026年10月22日
    300
  • 阿里云服务器配置怎么选?2026年云服务器选购指南

    新手选购阿里云服务器,核心结论是:个人博客或测试环境首选2核4G内存的通用型实例,配合50G系统盘和3M带宽即可满足需求;若运行高并发Web应用或数据库,则需升级至4核8G及以上配置,并优先选择SSD云盘以保障I/O性能,在2026年的云计算市场,阿里云依然占据着国内公有云的主导地位,对于刚接触云服务的开发者或……

    2026年6月26日
    5700
  • 服务器53端口可以用于什么?服务器53端口开放用途及安全风险

    服务器53端口可以承载DNS查询与响应,是互联网域名解析体系的基石;53端口是DNS服务的默认端口,UDP为主、TCP为辅,承担着将域名转换为IP地址的核心任务,53端口为何专属于DNS?历史标准化:1983年RFC 883首次定义DNS协议,明确53端口为DNS服务端口;1987年RFC 1035进一步规范U……

    2026年4月14日
    6400
  • 服务器怎么查看SVN账号密码,svn密码保存在哪个文件?

    服务器忘记SVN密码怎么办?先分清查看场景很多朋友在服务器上折腾SVN时,最常遇到的情况是:svn账号密码在哪看,这里有一个关键前提,SVN本身并不像数据库那样有一个统一管理账号密码的表,它的账号密码存储位置和格式完全取决于你当初是用哪种方式搭建的,独立SVN服务,账号密码写在passwd文件里如果你用的是最常……

    2026年9月18日
    200
  • 北京大带宽服务器租用怎么计费,有哪些收费模式?

    北京大带宽服务器租用的计费方式主要分为固定带宽月付、按量流量计费、以及BGP多线带宽叠加三种,其中按固定带宽包月并选择独享BGP线路是多数企业的首选,核心成本由带宽大小、IP数量、防御值三者共同决定,如果你正在对比机房报价,却发现每家的计费逻辑都不一样,很容易看花眼,有的标价低,点进去才发现流量费另算;有的写着……

    2026年10月16日
    000

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注