golang gin static 强制以文件方式下载

更新日期: 2025-12-11 阅读次数: 49 字数: 840 分类: golang

用 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 头

本地的 http 头

线上的 cloudflare 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 头,其他头也是正常的。

本地环境,会看到多了 Content-Disposition 头

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

cloudflare 返回头多了 Content-Disposition 头

先不管了,目前功能正常了就行,后面遇到问题再优化。

DeepSeek 的观点是,最常见的罪魁祸首是 Cloudflare 的缓存规则和优化功能覆盖了原始响应头。建议先关闭所有优化功能测试,然后逐个开启定位问题。

关于作者 🌱

我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式