文件API - 将Blob转换为JSON

40

我正在尝试使用HTML5、WebSocket和File API进行一些实验。 我正在使用Tomcat7 WebSocket实现。 我能够从servlet发送和接收文本消息。现在我想做的是从servlet向客户端发送JSON对象,但我想避免文本消息,以跳过客户端上的JSON解析(或类似操作),所以我正在尝试发送二进制消息。 servlet部分非常简单:

String s = "{arr : [1,2]}";
CharBuffer cbuf = CharBuffer.wrap(s);      
CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();      
getWsOutbound().writeBinaryMessage(encoder.encode(cbuf));
getWsOutbound().flush();

在这条消息之后,客户端上显示我收到了一个二进制帧,它被转换为Blob对象(http://www.w3.org/TR/FileAPI/#dfn-Blob)。 问题是:是否可以从Blob中获取JSON对象? 我查看了FileReader接口(http://www.w3.org/TR/FileAPI/#FileReader-interface),并使用了以下代码来检查FileReader的功能(第一行创建一个全新的Blob,因此您可以随时进行测试):
var b = new Blob([{"test": "toast"}], {type : "application/json"});
var fr = new FileReader();
fr.onload = function(evt) {
    var res = evt.target.result;
    console.log("onload",arguments, res, typeof res);
};
fr.readAsArrayBuffer(b);

使用我在文件读取器实现中看到的所有“readAs…”方法(我正在使用Chrome 22)。无论如何,我没有找到有用的东西。
你有什么建议吗?谢谢。

1
你认为如何将JSON字符串作为二进制消息发送?JSON只是对象的一种编码方式,你无法真正发送依赖于实现的二进制结构,需要通过某些“解析”函数来绕过这个问题。 - Bergi
是的,你说得对,这毫无意义。谢谢! - Antonio
4个回答

36
你应该尝试使用readAsText(),而不是readAsArrayBuffer()(JSON 最终是文本形式)。
同时,你还错过了将对象转化为 JSON 文本的步骤。
var b = new Blob([JSON.stringify({"test": "toast"})], {type : "application/json"}),
    fr = new FileReader();

fr.onload = function() {
    console.log(JSON.parse(this.result))
};

fr.readAsText(b);

22

要将包含JSON数据的Blob/File转换为JavaScript对象,请使用以下代码:

JSON.parse(await blob.text());

例子:

选择一个 JSON 文件,然后在浏览器控制台中使用它(json对象)。

const input = document.createElement("input");
input.type = "file";
input.accept = "application/json";
document.body.prepend(input);
input.addEventListener("change", async event => {
    const json = JSON.parse(await input.files[0].text());

    console.log("json", json);
    globalThis.json = json;
});


请注意:要在这里的控制台中访问“json”变量,您需要将控制台的上下文从“top”更改为“IFrame”。 - KeyKi
顺便提一下,您可以在任何需要“加载”JSON文件内容以实现某些目的的网站上(在浏览器控制台中)运行此示例代码。如果输入被CSS隐藏,您可以通过input.click();打开文件选择器。 - KeyKi
如果Blob的大小大于等于0.5GB,则在Chrome中无法正常工作,因为无法创建如此大的字符串。 - Don Hatch

15

你现在做的概念上是错误的。JSON是一个对象的字符串表示形式,而不是对象本身。因此,当您发送JSON的二进制表示到网络时,您实际上是发送了该字符串的二进制表示。无论如何,客户端都需要解析JSON将其转换成JavaScript对象。

你应该总是将JSON作为文本发送到客户端,并始终调用JSON.parse。否则你会面临很多麻烦。


就像我对Bergi所说的那样,正如你一开始所说的那样,这个问题在概念上是错误的。谢谢。 - Antonio
太酷了!我也可以问同样的问题。 - Franz Noel
16
问题本身没有问题。一个合理的情况是当服务器可以用不同的内容类型进行响应时,例如成功时返回Excel文件,错误时返回JSON。 - Somnium

2
let reader = new FileReader()
      reader.onload = e => {
        if (e.target.readyState === 2) {
          let res = {}
          if (window.TextDecoder) {
            const enc = new TextDecoder('utf-8')
            res = JSON.parse(enc.decode(new Uint8Array(e.target.result))) //转化成json对象
          } else {
            res = JSON.parse(String.fromCharCode.apply(null, new Uint8Array(e.target.result)))
          }

          console.info('import-back:: ', res)


        }
      }

      reader.readAsArrayBuffer(response)

2
虽然这可能回答了问题,但你应该[编辑]你的答案,包括一些上下文来解释你的代码是如何回答问题的。这样对于那些以后遇到相同问题的人来说会更有用。 - Hoppeduppeanut

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接