【问题标题】:File Download works with Chrome but not in Firefox when downloading golang generated file下载 golang 生成的文件时,文件下载适用于 Chrome,但不适用于 Firefox
【发布时间】:2018-09-28 21:32:29
【问题描述】:

我有一个简单的 golang/gin-gonic REST 服务,可根据/api/billing 的请求提供一份 Excel 报告。当请求者将接受标头设置为application/vnd.openxmlformats-officedocument.spreadsheetml.sheet 时,将提供一个 Excel 文件,否则为 json。这段代码在 Chrome 和 IE 中运行良好,但在 Firefox 中无法运行,我不知道为什么。

在 FF 调试器中,我看到实际内容已传输到浏览器,但 FF 并未向用户提供下载对话框。因此,对于用户来说,如果他点击链接,就好像什么都没有发生。

我已经检查过弹出窗口没有被 FF 阻止,我还禁用了其他安全功能 https://support.mozilla.org/1/firefox/62.0.2/Darwin/de/phishing-malware 以防万一。我还重新安装了普通的 FF,没有任何扩展和任何更改。 Windows 上的 FF 也是如此。

r.GET("/api/billing", func(c *gin.Context) {
        if c.GetHeader("Accept") == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" {
            b := api.GetBillingReportExcel()
            extraHeaders := map[string]string{
                "Content-Disposition": "attachment;filename='BillingReport.xlsx'",
                "Content-Transfer-Encoding": "binary",
                "Content-Description": "Excel Billing Report",
            }
            c.DataFromReader(200, int64(b.Len()),"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",&b,extraHeaders)
        }else {
            billingTenants, _ := cache.Get(c.Request.RequestURI)
            c.JSON(200, GetBillingData())
        }
})

以下是 FF 和 Chrome 的请求标头

HTTP 请求:

    Host: localhost:8081
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0
    Accept: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    Accept-Language: de,en-US;q=0.7,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://localhost:8081/
    Connection: keep-alive

回应

    HTTP/1.1 200 OK
    X-Powered-By: Express
    content-description: Excel Billing Report
    content-disposition: attachment; filename='BillingReport.xlsx'
    content-length: 11397
    content-transfer-encoding: binary
    content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    date: Tue, 25 Sep 2018 12:17:41 GMT

【问题讨论】:

  • RFC 建议 http 标头中的带引号的字符串应该用双引号 (") 引用。我认为这就是问题所在。
  • 而且根本不需要双引号,除非你的文件名中有空格。

标签: firefox go attachment go-gin


【解决方案1】:

您可能需要为 Content Disposition filename 使用双引号 (") 而不是单引号 ('):

extraHeaders := map[string]string{
  "Content-Disposition": `attachment; filename="BillingReport.xlsx"`,
  // Note the double quotes -------------------^------------------^

RFC 2616 Section 19.5.1 "Content-Disposition":

如果用户请求将内容保存到文件中,则建议使用 Content-Disposition 响应头字段作为源服务器建议默认文件名的一种方式...

    content-disposition = "Content-Disposition" ":"
                          disposition-type *( ";" disposition-parm )
    ...
    filename-parm = "filename" "=" quoted-string

还有Section 2.2 "Basic Rules":

如果使用双引号括起来,则将文本字符串解析为单个单词。

  quoted-string  = ( <"> *(qdtext | quoted-pair ) <"> )

RFC 6266 定义了额外的规则,但上面的简单引用是最简单的。

【讨论】:

    【解决方案2】:

    我尝试了几天来解决这个问题。但是,我在没想到的地方找到了罪魁祸首。最后是前端应用程序的行为,因为我的印象是它只是一个被调用的链接,我错了。

    但我想指出,我可以成功验证浏览器不关心 Content-Disposition 是否有 '" 或根本没有引用。

    上面的 gin/golang 也可以正常工作。

    感谢大家帮助我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-24
      • 1970-01-01
      • 2013-09-30
      • 2012-06-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多