从JavaScript二进制字符串创建Blob或文件会更改字节数? [英] Creating a Blob or a File from JavaScript binary string changes the number of bytes?

查看:144
本文介绍了从JavaScript二进制字符串创建Blob或文件会更改字节数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

 >>> reader.result 
GIF89a ÿÿÿÿÿÿ!þ用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文件API读作文本和二进制文件



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



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



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



谢谢!

解决方案


看来,当从二进制(javascript)字符串创建Blob时,带有字符编码的内容最终会重新排列结果。


是的。 您阅读的那篇文章很好地解释了如何构建二进制字符串。



Blob 构造函数相比之下



  1. s 成为将[字符串]转换为 Unicode
    字符
    序列的结果使用算法
    WebIDL 中执行此操作。

  2. s 编码为 UTF-8 并将结果字节附加到[blob]。








我们确定如果你直接读取一个ArrayBuffer,然后通过首先使用Uint8Array创建blob,那么字节就是rk out就好了。


是的,这就是应该如何工作的。只需在Typed Array上进行加密,你可以单独处理字节,而不是在某些字符串上。


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


再次:尽量不要。 二进制字符串已弃用


我想弄清楚如何将二进制字符串直接转换为Blob。在将它们放入Blob / File之前,我是否需要取得解密结果(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);


I have been playing with a few JS encryption libraries (CryptoJS, SJCL) and discovered problems related to the Blob/File APIs and JavaScript "binary strings".

I realized that the encryption isn't even really relevant, so here's a much simplified scenario. Simply read a file in using readAsBinaryString and then create a 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...}

I have created a JSFiddle that will basically do the above: it simply reads any arbitrary file, creates a blob from it, and outputs the length vs size: http://jsfiddle.net/6L82t/1/

It appears that, when creating the Blob from the "binary (javascript) string", something with character encoding ends up munging the result.

If a non-binary file is used, you will see that the lengths of the Blob and the original binary string are identical.

So there is something that happens when trying to create a Blob/File from a non-plaintext Javascript string, and I need whatever that is to not happen. I think it may have something to do with the fact that JS strings are UTF-16?

There's a (maybe) related thread here: HTML5 File API read as text and binary

Do I need to possibly take the decrypted results (UTF-16) and "convert" them to UTF-8 before putting them in a Blob/File?

Working with someone in #html5 on Freenode, we determined that if you read an ArrayBuffer directly and then create the blob from that by first using a Uint8Array, the bytes work out just fine. You can see a fiddle that essentially does that here: http://jsfiddle.net/GH7pS/4/

The issue is, at least in my scenario, I am going to end up with a binary string and would like to figure out how to directly convert that into a Blob so that I can then use html5's download to allow the user to click to download the blob directly.

Thanks!

解决方案

It appears that, when creating the Blob from the "binary (javascript) string", something with character encoding ends up munging the result.

Yes. That post you read explains well how a "binary string" is constituted.

The Blob constructor in contrast does

  1. Let s be the result of converting [the string] to a sequence of Unicode characters using the algorithm for doing so in WebIDL.
  2. Encode s as UTF-8 and append the resulting bytes to [the blob].


We determined that if you read an ArrayBuffer directly and then create the blob from that by first using a Uint8Array, the bytes work out just fine.

Yes, that's how it is supposed to work. Just do the encryption on a Typed Array where you deal with the bytes individually, not on some string.

The issue is, at least in my scenario, I am going to end up with a binary string

Again: Try not to. binary strings are deprecated.

I would like to figure out how to directly convert a binary string into a Blob. Do I need to possibly take the decrypted results (UTF-16) and "convert" them to UTF-8 before putting them in a Blob/File?

No, better don't try to do any string conversions. Instead, construct a Uint8Array(Uint8Array) for the bytes that you want to get from the binary string.

This should do it (untested):

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

这篇关于从JavaScript二进制字符串创建Blob或文件会更改字节数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆