下载大尺寸json时如何解决Uncaught RangeError

Posted

技术标签:

【中文标题】下载大尺寸json时如何解决Uncaught RangeError【英文标题】:How to solve Uncaught RangeError when download large size json 【发布时间】:2017-02-18 22:41:30 【问题描述】:

我正在尝试下载大型 json 数据。 但它导致Uncaught RangeError: Invalid string length

请帮忙解决这个问题,在此先感谢。

这里是 Jsfiddle:http://jsfiddle.net/sLq3F/456/

【问题讨论】:

您正在尝试获取 181 兆字节的文件。 (阅读此问题的人请注意:如果您单击该小提琴链接,请准备好让您的 CPU 风扇旋转。) 是的,有很多数据要在那里进行两次字符串化。该数据对象中的数组有 206560 项。 没有得到足够的重视,因为这里没有问题。有一条错误消息和一个链接。 根据我的说法,您必须从服务器端获取 JSON,而不是从 JQuery 获取。 【参考方案1】:

我猜您需要遍历 JSON 文件中的某些内容并将其拆分为更易于管理的字符串。

汤姆

你有一个示例 sn-p JSON 文件吗?

【讨论】:

【参考方案2】:

你有运行 php 的服务器吗?

如果你这样做,我相信你必须绝对检查你的 PHP.ini 文件或运行一个 phpinfo 页面,因为 php 设置确实限制了文件传输的大小,即使它不是外部请求。它可以用其他语言做到这一点,但除了 PHP 之外,我从来没有遇到过这个问题。

附:我没有看到文件的大小

【讨论】:

【参考方案3】:

我认为您的 json 文件是“JSON 太大”的场景之一。你知道,如果 json 文件有这么多的记录(确切地说,根据测试,100000 条记录会使浏览器挂起,而更多的记录则无法在许多浏览器中加载)它不建议使用。

您可以阅读这篇文章了解更多信息:HOW BIG IS TOO BIG FOR JSON?

【讨论】:

【参考方案4】:

您可以使用fetch()Response.body.getReader(),它返回ReadableStreamTextDecoder()Blob()URL.createObjectURL()

注意,在具有有限RAM 或可用磁盘空间不足的设备上,在Save File 对话框中单击Save 后,4:20Save File 对话框关闭之前已经过去了四分二十秒,然后是另外一个在文件管理器 GUI 中从文件中删除 .crdownload 扩展名之前的分 30 秒 1:30。在文件下载到文件系统并且Save File 对话框可见的第一个4:20 期间,鼠标指针是可移动的,尽管UI 暂时对单击或尝试更改选项卡没有响应。当Save File 对话框关闭并且文件仍在下载到文件系统时,扩展名为.crdownload,UI 将恢复正常功能。

在上述过程结束时,文件已成功下载到本地文件系统,总大小为189.8 MB (189,778,220 bytes)

<!DOCTYPE html>
<html>

<head>
  <style>
    code 
      color:navy;
      background-color:#eee;
      padding:2px;
    
  </style>
</head>

<body>
  <button>Request File</button><br>
  <progress min="0" max="189778220" value="0"></progress>
  <output></output>
  <br><br>
  <label></label>
  <script>
    var url = "https://raw.githubusercontent.com/zemirco/sf-city-lots-json/master/citylots.json";
    var button = document.querySelector("button");
    var progress = document.querySelector("progress");
    var label = document.querySelector("label");
    var output = document.querySelector("output");
    
    var request = (url) => 
      
      label.innerHTML = `Requesting <code>$url</code> at $new Date().<br><br>`;
      
      return fetch(url)
      .then(response => response.body.getReader())
      .then(reader => 
        var decoder = new TextDecoder();
        var json = "";
        label.innerHTML += `Request successful.<br><br>Reading request body at $new Date().<br><br>`;
        return reader.read().then(function processData(result) 
            if (result.done) 
              // do stuff when `reader` is `closed`
              return reader.closed.then(function() 
                // return `json` string
                return json;
              );
            ;
            json += decoder.decode(result.value);
            output.innerHTML = ` $json.length of $progress.max bytes read`;
            progress.value = json.length;
            return reader.read().then(processData)
          )
          .then(function(data) 
            var message = `Reading of <code>$url</code> complete at $new Date(). <br><br>` 
                               + `$data.length total bytes read. `
                               + `Please allow up to 4 minutes for file to download `
                               + `to filesystem after clicking <code>Save</code>.<br><br>`;
            label.innerHTML += message;
            
            var blob = new Blob([data], 
              type: "application/json"
            );
            var file = URL.createObjectURL(blob);
            var a = document.createElement("a");
            a.download = "citylots.json";
            a.href = file;
            document.body.appendChild(a);
            a.click();
            var closeBlob = (e) => 
              window.removeEventListener("focus", closeBlob);
              blob.close();
              URL.revokeObjectURL(file);
            ;
            window.addEventListener("focus", closeBlob);
            return message.replace(/<[^>]*>/g, "");
          )
          .catch(function(err) 
            console.log("err", err)
          )
      );
    
    
    var handleRequest = (e) => 
      button.setAttribute("disabled", "disabled");
      request(url).then(function(message) 
        console.log(message);
        button.removeAttribute("disabled");
      )
    ;
    
    button.addEventListener("click", handleRequest);
  </script>
</body>
</html>

plnkrhttps://plnkr.co/edit/gewixzHZSKRXquZ2OVF2?p=preview

【讨论】:

当我点击按钮时,它似乎正在加载,但经过一段时间后它导致 DevTools 与页面断开连接。请帮助我,.. @selvarajmas 单击Save 后,Save File 对话框需要 4 多分钟才能关闭。在文件写入本地文件系统完成之前又过了一分半钟。您试用的设备上有多少RAM 我已安装内存(RAM) 3GB 您在javascript 尝试过哪个浏览器? 哪个版本的chrome?

以上是关于下载大尺寸json时如何解决Uncaught RangeError的主要内容,如果未能解决你的问题,请参考以下文章

jsonp 跨域Uncaught SyntaxError: Unexpected token :解决方法

如何读取具有不同数据类型的大型 JSON 文件

EasyNTD线上报错“Uncaught TypeError”该如何解决?

EasyNTD线上报错“Uncaught TypeError”该如何解决?

在 javascript 中通过 django 模板检索 json 数据时出错,在参数列表后给出 Uncaught SyntaxError: missing )

Uncaught (in promise) SyntaxError: Unexpected end of JSON input error