【问题标题】:Creating a Blob or a File from JavaScript binary string changes the number of bytes?从 JavaScript 二进制字符串创建 Blob 或文件会更改字节数?
【发布时间】:2014-05-21 22:38:49
【问题描述】:

我一直在使用一些 JS 加密库(CryptoJS、SJCL)并发现与 Blob/File API 和 JavaScript“二进制字符串”相关的问题。

我意识到加密甚至不是真正相关的,所以这里有一个非常简化的场景。只需使用 readAsBinaryString 读取一个文件,然后创建一个 Blob:

>>> reader.result
"GIF89a����ÿÿÿÿÿÿ!þCreated with GIMP�,�������D�;"
>>> reader.result.length
56
>>> typeof reader.result
"string"
>>> blob = new Blob([reader.result], {type: "image/gif"})
Blob { size=64, type="image/gif", constructor=function(), more...}

我创建了一个 JSFiddle,它基本上可以完成上述工作:它只是读取任意文件,从中创建一个 blob,然后输出长度与大小: http://jsfiddle.net/6L82t/1/

看起来,当从“二进制 (javascript) 字符串”创建 Blob 时,带有字符编码的东西最终会改变结果。

如果使用非二进制文件,你会看到 Blob 的长度和原始二进制字符串的长度是相同的。

因此,当尝试从非纯文本 Javascript 字符串创建 Blob/文件时会发生一些事情,我需要任何不会发生的事情。我认为这可能与 JS 字符串是 UTF-16 的事实有关?

这里有一个(可能)相关的线程: HTML5 File API read as text and binary

在将它们放入 Blob/文件之前,我是否需要获取解密结果 (UTF-16) 并将它们“转换”为 UTF-8?

在 Freenode 上与 #html5 中的某个人合作后,我们确定如果您直接读取 ArrayBuffer,然后首先使用 Uint8Array 从中创建 blob,那么字节就可以正常工作。你可以在这里看到一个基本上可以做到这一点的小提琴: http://jsfiddle.net/GH7pS/4/

问题是,至少在我的场景中,我最终会得到一个二进制字符串,并想弄清楚如何直接将其转换为 Blob,以便我可以使用 html5 的下载来允许用户点击直接下载blob。

谢谢!

【问题讨论】:

  • 您确实意识到您的帖子already has a comprehensive edit history,对吗?您可以通过将鼠标悬停在 SE 网页上获取发布在 SE 网页上的任何时间的准确时间戳;试试你名字上方的“2 小时前询问”。

标签: javascript html


【解决方案1】:

看起来,当从“二进制 (javascript) 字符串”创建 Blob 时,带有字符编码的东西最终会改变结果。

是的。 That post you read 很好地解释了“二进制字符串”是如何构成的。

相比之下,Blob constructor 可以

  1. s 是使用算法将[字符串] 转换为Unicode characters 序列的结果 在WebIDL 这样做。
  2. s 编码为UTF-8 并将生成的字节附加到[blob]。

我们确定,如果您直接读取 ArrayBuffer,然后首先使用 Uint8Array 从中创建 blob,那么字节就可以正常工作。

是的,它应该是这样工作的。只需对类型化数组进行加密,在其中单独处理字节,而不是在某些字符串上。

问题是,至少在我的场景中,我最终会得到一个二进制字符串

再次:尽量不要。 binary strings are deprecated.

我想弄清楚如何将二进制字符串直接转换为 Blob。在将它们放入 Blob/文件之前,我是否需要获取解密结果 (UTF-16) 并将它们“转换”为 UTF-8?

不,最好不要尝试进行任何字符串转换。相反,为要从二进制字符串中获取的字节构造一个 Uint8Array(Uint8Array)。

应该这样做(未经测试):

var bytes = new Uint8Array(str.length);
for (var i=0; i<str.length; i++)
    bytes[i] = str.charCodeAt(i);

【讨论】:

  • 这完全有效。我想后续问题专门与 CryptoJS 相关——当你解密内容并收到你的“WordArray”时,有没有办法直接进入 ArrayBuffer 而无需先转换为字符串,然后将其放入 Uint8Array 中使用对于blob?
  • 后续:看起来有人做了一些不涉及字符串转换的事情(对字节进行操作):groups.google.com/d/msg/crypto-js/TOb92tcJlU0/Eq7VZ5tpi-QJ 似乎这样有效。太棒了!
  • 是的,这可能是一个很好的单独问题(标记为cryptojs)。我不知道他们有自己的数据类型,我必须在他们的文档中查找这些内容。
  • @ErikJacobs 感谢您发布链接!
  • 感谢您从二进制字符串转换为字节数组!
猜你喜欢
  • 2016-02-10
  • 2012-05-08
  • 2015-03-04
  • 1970-01-01
  • 2011-06-10
  • 2019-01-13
  • 2016-02-29
相关资源
最近更新 更多