我有一个 JAX-RS REST-Service,它可以生成 CSV 文件并将其流式传输回浏览器。一切都设置为 UTF-8,所以我通过浏览器下载的文件也是一个有效的 UTF-8 文件(没有 BOM),它在 Notepad++、Sublime 等中向我显示有效、可读的 UTF-8 变音符号等。
在 Excel 中打开这样的文件会导致不可读的元音变音等,因为 Excel 显然尝试使用另一个字符集(我猜是 CP-1252,但这并不重要)打开它。
通过 Notepad++ 保存带有 BOM 的文件并在 Excel 中重新打开它效果很好。似乎 BOM 检测是 Excel 用于检测 UTF-8 的唯一方法。无论如何 - 我认为添加 BOM 可以有所帮助...
做到了。相同的结果。一段时间后,我发现 BOM 在某些情况下会被删除:如果我在 BOM 之前添加任何字符,我可以在我的十六进制编辑器中看到 BOM。删除该字符后,BOM 将不再存在。
当我继续通过 cURL 下载文件时,我真的很惊讶。 BOM 就在那里!在此之前,我认为这可能与我的应用程序、内容类型、编码、HTTP header 等有关 - 但所有这些似乎都很好。
现在,经过几个小时的尝试不同的事情之后,对于如何告诉浏览器保留 BOM 有什么想法吗?我可以设置任何 HTTP header 吗?由于 Chrome、Internet Explorer、Edge、Firefox 都删除了 BOM,这对我来说听起来有点像浏览器约定...
非常感谢您的高度赞赏的帮助!
编辑:感谢 sideshowbarker 的回答,我找到了一种解决方法,即在内容前面添加两个 BOM,这样在浏览器删除第一个 BOM 后,就会剩下一个 BOM。
最佳答案
解决方法(来自评论):由于仅读取前三个字节,因此您可以在源前面添加两个 BOM,这将导致下载的文件为带有 BOM 的有效 UTF-8 文件。
具体就 Excel 而言:根据 https://stackoverflow.com/a/16766198/1143392 的答案,较新版本的 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:
Let buffer be an empty byte sequence.
Read three bytes from stream into buffer.
If buffer does not match 0xEF 0xBB 0xBF, prepend buffer to stream.
Let output be a code point stream.
Run UTF-8’s decoder with stream and output.
Return output.
第 3 步导致 BOM 被剥离。
考虑到编码规范的要求,我认为没有办法告诉浏览器保留 BOM。
关于curl - 在浏览器下载中保留 UTF-8 BOM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42715966/