18

以下代码(供应商规范化)运行良好,在 Firefox 8 中显示“➀➁➂ Test”,但在 Google Chrome 中显示“➀âžâž‚ Test”。除了使用文件系统 API 将文件写入临时文件系统之外,有什么方法可以保留 Google Chrome 中的 blob 编码?

var b = new Blob(["➀➁➂ Test"], {type: "text/plain;charset=UTF-8"});
var url = URL.createObjectURL(b);
open(url);
4

3 回答 3

17

new Blob(["➀➁➂ Test"])将生成一个表示编码为 UTF-8 的文本的 Blob。

浏览器假定文本文件应该在 ISO 中读取是一个奇怪的选择 IMM。

当浏览器将通过 blob URI 提供它时,附加{ type: "text/plain;charset=utf8" }应该生成正确的标头。Content-TypeChrome 没有open()听起来像一个错误。

现在,您可以通过在文本文件开头添加 BOM 序列来解决此问题,以便 Chrome 将其检测为 UTF,即使没有Content-Type信息:

var BOM = new Uint8Array([0xEF,0xBB,0xBF]);
var b = new Blob([ BOM, "➀➁➂ Test" ]);
var url = URL.createObjectURL(b);
open(url);

var BOM = new Uint8Array([0xEF,0xBB,0xBF]);

var blob_BOM = new Blob([ BOM, "➀➁➂ Test" ]);
var url_BOM = URL.createObjectURL(blob_BOM);
// for demo we also create one version without BOM
var blob_noBOM = new Blob([ "➀➁➂ Test" ]);
var url_noBOM = URL.createObjectURL(blob_noBOM);

document.querySelector('.BOM').href = url_BOM;
document.querySelector('.no-BOM').href = url_noBOM;

// to check whether they contain the same data, apart from the BOM
(async() => {
  const buf_BOM = await blob_BOM.slice(3).arrayBuffer(); // remove BOM sequence
  const buf_noBOM = await blob_noBOM.arrayBuffer();
  
  console.log( 'with BOM text data:' );
  console.log( JSON.stringify( [...new Uint8Array( buf_BOM )] ) );
  console.log( 'without BOM text data:' );
  console.log( JSON.stringify( [...new Uint8Array( buf_noBOM )] ) );

})();
<a class="BOM">open file with BOM</a><br>
<a class="no-BOM">open file without BOM</a>

于 2020-05-08T02:18:12.237 回答
12

Gecko (Firefox)、WebKit (Safari、Chrome) 和 Opera 支持以 64 进制编码字符串的非标准btoa函数。为了获得包含编码为 UTF-8 的字符串的 64 进制字符串,您需要使用encodeURIComponent-unescape技巧. encodeURIComponent将字符串编码为 UTF-8 URL,但将unescape每个字符串解码%xx为单个字符。btoa期望您想要的任何编码的二进制字符串。

var base64 = btoa(unescape(encodeURIComponent(data)));
window.open("data:text/plain;charset=UTF-8;base64,"+base64,"UTF-8 Text");

当然这在 IE 中不起作用,但我认为 IE 10 将支持Blob-API。谁知道它将如何处理编码。

PS:IE 似乎无法window.opendata:-urls 并且无论如何都会有一个荒谬的小 url 长度限制。

PPS:这在 Chrome 中适用于我:

var b = new Blob(["➀➁➂ Test"],{encoding:"UTF-8",type:"text/plain;charset=UTF-8"});
var url = URL.createObjectURL(b);
window.open(url,"_blank","");
于 2012-04-09T03:31:01.080 回答
1

问题是 Chrome 中新标签页的默认页面编码。当新窗口打开时(在 之后window.open(url)),从 Chrome 菜单中选择查看 > 编码 > Unicode。这在 Chrome 13 中将显示的文本从“➀âžâž‚ Test”更改为“➀➁➂ Test”。

如果您想要一个解决方案,无论默认编码如何,您都可以在新窗口中打开 blob,那么您可以依靠 iframe 中的文档在未明确指定其自己的编码时将继承父文档编码这一事实。因此,您可以打开一个带有Content-Type:text/html; charset=utf-8标题的空白 HTML 文档的窗口,然后将 iframe 附加到正文,并将src属性设置为 blob URL。

于 2011-08-29T16:07:32.597 回答