Golang Fiber文件接口报Directory index is forbidden错误
问题原因
调用Fiber的c.SendFile/c.Download返回「Directory index is forbidden」错误,核心是传入的目标路径指向了目录而非具体文件:
- 路由通配符匹配时未传具体文件名,
c.Params("file")取到空值,最终拼接的路径是./files/也就是存储目录本身 - 传入的参数值本身对应
./files下的子目录,而非具体文件
Fiber默认禁止返回目录索引内容,遇到目录路径就会抛出该错误。此外原有写法存在路径穿越安全风险,传入../开头的参数可以读取项目目录外的敏感文件。
修复方案
- 对传入的文件名参数做合法性校验,拦截空值、包含
..路径穿越符、绝对路径形式的非法参数 - 拼接文件路径时使用
filepath.Join替代手动字符串拼接,自动处理路径分隔符问题 - 调用文件发送方法前,先校验目标路径存在且不是目录,避免把目录路径传给框架方法
- 非必要不要开启Fiber的目录索引配置,避免暴露服务器文件结构
修复后的代码实现:
import ( "os" "path/filepath" "strings" "github.com/gofiber/fiber/v2" ) func GetFile(c *fiber.Ctx) error { fileName := c.Params("file") // 拦截空文件名 if fileName == "" { return c.Status(fiber.StatusBadRequest).SendString("缺少文件名参数") } // 拦截路径穿越风险 if strings.Contains(fileName, "..") || strings.HasPrefix(fileName, "/") || strings.HasPrefix(fileName, "\\") { return c.Status(fiber.StatusBadRequest).SendString("非法文件名") } // 拼接安全路径 filePath := filepath.Join("./files", fileName) // 校验目标为普通文件 fileInfo, err := os.Stat(filePath) if err != nil || fileInfo.IsDir() { return c.Status(fiber.StatusNotFound).SendString("目标文件不存在") } return c.SendFile(filePath) } func DownloadFile(c *fiber.Ctx) error { fileName := c.Params("file") if fileName == "" { return c.Status(fiber.StatusBadRequest).SendString("缺少文件名参数") } if strings.Contains(fileName, "..") || strings.HasPrefix(fileName, "/") || strings.HasPrefix(fileName, "\\") { return c.Status(fiber.StatusBadRequest).SendString("非法文件名") } filePath := filepath.Join("./files", fileName) fileInfo, err := os.Stat(filePath) if err != nil || fileInfo.IsDir() { return c.Status(fiber.StatusNotFound).SendString("目标文件不存在") } return c.Download(filePath) }
补充:如果路由注册为
/api/file/*file这类通配符形式,访问路径未带具体文件名时,参数会取空值,上述校验逻辑会直接返回参数错误,不会触发框架的目录索引拦截逻辑。
内容的提问来源于stack exchange,提问作者Akik jamil
相关产品推荐
相关产品推荐

