filesystem中间件的browse:true仅在请求路径为有效目录且无对应文件时自动返回html索引页,不提供api式json文件列表;需用os.readdir等标准库手动实现。

FileSystem 中间件不支持目录浏览(Browse: true)时列出文件列表
直接用 filesystem.New() 配置 Browse: true 并不能让你“列出目录内容”——它只在请求路径匹配一个**不存在的文件但指向有效目录**时,自动渲染 HTML 目录索引页。这不是 API 式的文件列表接口,也不返回 JSON 或结构化数据。
常见错误现象:curl http://localhost:3000/assets/ 返回 404,或返回 HTML 页面但你想要的是 GET /api/files 这样的 JSON 列表。
-
Browse: true仅对未命中具体文件、且路径末尾是/的请求生效(例如访问/assets/,而/assets/logo.png存在则不会触发) - 它依赖底层
http.Dir的行为,不暴露原始文件条目供 Go 代码遍历 - 无法控制排序、过滤、权限、递归深度等——纯静态服务逻辑
想真正列出目录文件?别用 Browse,自己写 handler + std::fs(Go 的 os.ReadDir)
Fiber 本身不提供目录枚举能力,filesystem 中间件也不是为这个设计的。你需要注册一个显式路由,用 Go 标准库读取目录并手动响应。
使用场景:构建管理后台的静态资源浏览器、调试用的资产清单、CI 构建产物查看页。
- 用
os.ReadDir("./assets")获取[]fs.DirEntry,比ioutil.ReadDir(已弃用)更轻量 - 注意路径安全:禁止用户传入
../类路径,必须做前缀校验(如strings.HasPrefix(path, "./assets")) - 避免暴露敏感文件:跳过以
.开头的条目(.git、.env),或白名单扩展名 - 示例片段:
app.Get("/api/files", func(c *fiber.Ctx) error {
entries, err := os.ReadDir("./assets")
if err != nil {
return c.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
files := make([]string, 0, len(entries))
for _, e := range entries {
if !e.IsDir() && !strings.HasPrefix(e.Name(), ".") {
files = append(files, e.Name())
}
}
return c.JSON(files)
})
为什么 filesystem.Config.Root 不能直接传变量或动态路径
filesystem.New() 初始化时要求 Root 是一个固定的 http.Dir 实例,它在启动时绑定路径并缓存文件系统句柄。你不能在 handler 里动态改它,也不能用 http.Dir(filepath.Join(base, userPath)) 拼接后传入——因为 http.Dir 的 Open 方法内部不做路径净化,会直接交给 OS,极易导致目录穿越漏洞。
- 所有通过
filesystem中间件暴露的路径,都必须是应用启动前就确定的静态目录 - 若需多租户或多目录支持,应注册多个独立中间件实例(如
app.Use("/public", fs1)和app.Use("/uploads", fs2)),而非运行时切换Root - 试图绕过限制(如用
os.Chdir+ 全局http.Dir("."))会导致并发不安全和不可预测行为
StrictRouting 对 /assets/ 这类路径的影响很实际
如果你注册了 app.Use("/assets", filesystem.New(...)),那么请求 /assets(无尾斜杠)会被 Fiber 当作精确匹配;而 /assets/(有尾斜杠)在 StrictRouting: true(默认)下会被视为不同路径,直接 404 —— 即使你开了 Browse: true,也根本进不到中间件里。
- 解决方法不是关
StrictRouting,而是显式挂载两次:app.Use("/assets", ...)和app.Use("/assets/", ...) - 或者加一个前置重定向中间件:
app.Use("/assets/", func(c *fiber.Ctx) error { return c.Redirect(c.OriginalURL()[0:len(c.OriginalURL())-1], 301) }) - 注意:重定向中间件必须放在
filesystem之前,否则无效
filesystem 中间件本质是封装 net/http.FileServer,它的边界很清晰:只做静态文件服务,不负责元数据操作。真要“列出目录”,就得跳出中间件思维,用标准库动手读——这反而是最可控、最安全的做法。











