最常见原因是路径没走对——ctx.sendfile接收的是服务端文件系统绝对路径或相对于当前工作目录的相对路径,不是url路径;例如访问/download/report.pdf却写ctx.sendfile("report.pdf"),会去进程启动目录而非项目根目录查找。

为什么 ctx.SendFile 有时返回 404 或空响应
最常见原因是路径没走对——ctx.SendFile 接收的是**服务端文件系统绝对路径或相对于当前工作目录的相对路径**,不是 URL 路径。比如你访问 /download/report.pdf,但代码里写 ctx.SendFile("report.pdf"),它会去当前进程启动目录下找,而不是项目根目录或静态目录。
实操建议:
- 用
filepath.Abs或filepath.Join显式拼出完整路径,例如:filepath.Join("assets", "reports", filename) - 下载前先用
os.Stat检查文件是否存在且可读,避免静默失败 - 不要依赖
http.Dir或中间件的静态路由逻辑——SendFile是独立 IO 操作,不经过静态文件中间件
如何让浏览器触发下载而非内嵌预览
默认情况下,浏览器根据 Content-Type 决定是下载还是打开(如 application/pdf 常被预览)。要强制下载,必须设置 Content-Disposition 响应头。
实操建议:
- 用
ctx.Attachment(filepath)替代ctx.SendFile:它自动设Content-Disposition: attachment; filename="xxx"和合理Content-Type - 如果需自定义文件名(比如原文件名含中文或想重命名),先调
ctx.Set("Content-Disposition", `attachment; filename="safe-name.pdf"`),再调ctx.SendFile - 中文文件名要用
filename*=UTF-8''...编码,否则可能乱码;推荐用mime.BEncoding.Encode处理
大文件下载卡顿或内存爆掉怎么办
ctx.SendFile 默认用 io.Copy 流式传输,通常没问题;但若文件极大(>100MB)或并发高,可能因未设超时、缓冲区不当或缺乏断点续传支持导致连接挂起或 OOM。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
实操建议:
- 加超时控制:在路由 handler 外层用
fiber.Timeout中间件,例如app.Get("/dl/*", fiber.Timeout(5*time.Minute)) - 避免把文件全读进内存:别用
ctx.Send+os.ReadFile,坚持用SendFile或Attachment - 需要断点续传(如视频/镜像下载),得手动解析
Range请求头,用http.ServeContent—— Fiber 不内置支持,得自己封装
生产环境要注意的权限与路径安全
用户传来的文件名若直接拼进路径,极易触发路径遍历攻击(如 ../../etc/passwd)。Fiber 不做自动过滤,必须由你校验。
实操建议:
- 禁止用户输入参与路径构造:从 URL 或 query 取参数后,只允许匹配白名单正则,例如
^[a-zA-Z0-9._-]+\.pdf$ - 用
filepath.Clean归一化路径后,检查是否仍在允许目录内,例如:strings.HasPrefix(cleanPath, allowedDir) - 下载目录建议设为只读,且不在 Web 根目录下;敏感文件(如日志、配置)绝不暴露下载接口
路径校验和文件存在性检查这两步漏掉任何一个,都可能让整个下载接口变成服务器探针入口。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










