用 golang gin static 实现了一个文件下载功能,同时下载前需要先鉴权。例如:
// serve /download under a group that enforces token validation
g := r.Group("/download")
g.Use(DownloadAuthMiddleware())
g.Static("/", downloadPath)
DownloadAuthMiddleware 是一个中间件,会判断文件下载链接中的 token 参数是否过期。
这个加载功能,在本地开发环境是一切正常的,但是到了线上,套上 cloudflare 之后,就出现了问题。例如:
下载一个 csv 的文件,本地浏览器打开,会自动触发浏览器的另存为的方式。 但是到了线上,变成了直接展示 csv 文件内容,变成了一个网页展示。
而且,下载链接如果直接右键保存,下载下来的 csv 文件名后缀,会被自动替换成了 txt 后缀。
HTTP 头对比
本地的 http 头

线上的 cloudflare http 头

会看到 cloudflare http 头没有 content type ...
添加 Content-Disposition 头信息
按照 AI 的提示,在中间件中添加了 Content-Disposition 头信息。如下:
// 强制下载
c.Header("Content-Disposition", "attachment; filename=\""+url.PathEscape(reqPath)+"\"")
Content-Disposition 是一个 HTTP 响应头(也可用于 MIME 邮件),主要作用是指示客户端如何处理响应内容,特别是控制文件的下载行为。
- 强制下载文件。例如:Content-Disposition: attachment; filename="example.pdf"
- 内联显示。例如:Content-Disposition: inline; filename="photo.jpg"
添加之后,线上的下载行为也正常了。
content type 依旧不对
本地环境,会看到多了 Content-Disposition 头,其他头也是正常的。

cloudflare 返回头,虽然多了 Content-Disposition 头,下载文件的扩展名正确了。但是 content type 依旧不对:

先不管了,目前功能正常了就行,后面遇到问题再优化。
DeepSeek 的观点是,最常见的罪魁祸首是 Cloudflare 的缓存规则和优化功能覆盖了原始响应头。建议先关闭所有优化功能测试,然后逐个开启定位问题。
关于作者 🌱
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式