在浏览器下载中保留 UTF-8 BOM

Preserve UTF-8 BOM in Browser Downloads

我有一个 JAX-RS REST-Service 可以生成 CSV 文件并将其流式传输回浏览器。一切都设置为 UTF-8,所以我通过浏览器下载的文件也是一个有效的 UTF-8 文件(没有 BOM),在 Notepad++、Sublime 等中显示有效、可读的 UTF-8 变音符号等。

虽然在 Excel 中打开这样的文件会导致不可读的变音符号等,因为 Excel 显然试图用另一个字符集打开它(我猜是 CP-1252,但事实并非如此真的很重要)。

通过 Notepad++ 保存带有 BOM 的文件,re-opening 它在 Excel 中效果很好。似乎 BOM 检测是 Excel 用来检测 UTF-8 的唯一方法。无论如何 - 我认为添加 BOM 可以帮助...

做到了。同样的结果。一段时间后,我发现 BOM 在某些情况下会被删除:如果我在 BOM 之前添加任何字符,我可以在我的 Hex-Editor 中看到 BOM。删除该字符后,BOM 将不再存在。

当我继续通过 cURL 下载文件时,我真的很惊讶。 BOM 在那里!在那之前,我认为它可能与我的应用程序、Content-Types、Encodigs、HTTP Headers 等有关 - 但它们似乎都很好。

现在,经过数小时的尝试不同的事情,关于如何让浏览器保留 BOM 有什么想法吗?我可以设置任何 HTTP Header 吗?由于 Chrome,Internet Explorer、Edge、Firefox 都删除了 BOM,这对我来说听起来有点像浏览器约定...

非常感谢您的大力帮助!

编辑: 感谢 sideshowbarker 的回答,我找到了一种解决方法,方法是在内容前添加两个 BOM,这样在浏览器删除第一个 BOM 后,还会剩下一个 BOM .

解决方法(来自评论):由于只读取前三个字节,您可以在源前添加两个 BOM,这将导致下载的文件是带有 BOM 的有效 UTF-8。

就 Excel 具体而言:根据 的回答,较新版本的 Excel(来自 Office 365)现在支持 UTF-8。

至于问题中描述的行为的原因:原因是,相关规范要求剥离 BOM,而这正是浏览器所做的。即浏览器符合the UTF-8 decode algorithm in the Encoding spec的要求,也就是这个:

To UTF-8 decode a byte stream stream, run these steps:

  1. Let buffer be an empty byte sequence.

  2. Read three bytes from stream into buffer.

  3. If buffer does not match 0xEF 0xBB 0xBF, prepend buffer to stream.

  4. Let output be a code point stream.

  5. Run UTF-8’s decoder with stream and output.

  6. Return output.

第 3 步是导致 BOM 被剥离的原因。

鉴于编码规范要求,我认为没有办法告诉浏览器保留 BOM。