Javascript 从浏览器下载JSON对象作为文件

Javascript 从浏览器下载JSON对象作为文件,javascript,json,Javascript,Json,我有以下代码让用户下载csv文件中的数据字符串 exportData = 'data:text/csv;charset=utf-8,'; exportData += 'some csv strings'; encodedUri = encodeURI(exportData); newWindow = window.open(encodedUri); 如果客户端运行代码,它会生成一个空白页面并开始下载csv文件中的数据 exportData = 'data:text/csv;charset=ut

我有以下代码让用户下载csv文件中的数据字符串

exportData = 'data:text/csv;charset=utf-8,';
exportData += 'some csv strings';
encodedUri = encodeURI(exportData);
newWindow = window.open(encodedUri);
如果客户端运行代码,它会生成一个空白页面并开始下载csv文件中的数据

exportData = 'data:text/csv;charset=utf-8,';
exportData += 'some csv strings';
encodedUri = encodeURI(exportData);
newWindow = window.open(encodedUri);
所以我试着用JSON对象这样做

exportData = 'data:text/json;charset=utf-8,';
exportData += escape(JSON.stringify(jsonObject));
encodedUri = encodeURI(exportData);
newWindow = window.open(encodedUri);
但我只看到一个页面上显示了JSON数据,并没有下载它

我做了一些研究,并声称可以工作,但我看不出我的代码有什么不同

我的代码中遗漏了什么吗


感谢阅读我的问题:)

尝试设置另一个MIME类型:
exportData='数据:应用程序/八位字节流;字符集=utf-8'

但“保存”对话框中的文件名可能存在问题。

找到了答案

var obj = {a: 123, b: "4 5 6"};
var data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(obj));

$('<a href="data:' + data + '" download="data.json">download JSON</a>').appendTo('#container');
varobj={a:123,b:456};
var data=“text/json;charset=utf-8,”+encodeURIComponent(json.stringify(obj));
$(“”).appendTo(“#container”);
对我来说似乎很好


**所有功劳都归于@cowboy ben alman,他是上述代码的作者**

链接的
下载属性是新的,在Internet Explorer中不受支持(请参见兼容性表)。对于这个问题的跨浏览器解决方案,我将看一看这将是一个纯JS版本(改编自cowboy):


以下是我为我的应用程序解决此问题的方法:

HTML:

JS(纯JS,这里不是jQuery):

在本例中,
storageObj
是要存储的js对象,而“scene.json”只是结果文件的一个示例名称

与其他建议方法相比,该方法具有以下优点:

  • 不需要单击任何HTML元素
  • 结果将按您的需要命名
  • 不需要jQuery
我需要这种行为而不需要显式单击,因为我想在某个时候从js自动触发下载

JS解决方案(无需HTML):


以下几点对我很有用:

/* function to save JSON to file from browser
* adapted from http://bgrins.github.io/devtools-snippets/#console-save
* @param {Object} data -- json object to save
* @param {String} file -- file name to save to 
*/
function saveJSON(data, filename){

    if(!data) {
        console.error('No data')
        return;
    }

    if(!filename) filename = 'console.json'

    if(typeof data === "object"){
        data = JSON.stringify(data, undefined, 4)
    }

    var blob = new Blob([data], {type: 'text/json'}),
        e    = document.createEvent('MouseEvents'),
        a    = document.createElement('a')

    a.download = filename
    a.href = window.URL.createObjectURL(blob)
    a.dataset.downloadurl =  ['text/json', a.download, a.href].join(':')
    e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
    a.dispatchEvent(e)
}
然后就这样称呼它

saveJSON(myJsonObject, "saved_data.json");

我最近不得不创建一个按钮,该按钮将下载一个包含所有大型值的json文件。我需要这个来和IE/Edge/Chrome一起工作。这就是我所做的:

function download(text, name, type)
    {
        var file = new Blob([text], {type: type});
        var isIE = /*@cc_on!@*/false || !!document.documentMode;
        if (isIE)
        {
            window.navigator.msSaveOrOpenBlob(file, name);
        }
        else
        {
            var a = document.createElement('a');
            a.href = URL.createObjectURL(file);
            a.download = name;
            a.click();
        }
     }

download(jsonData, 'Form_Data_.json','application/json');
edge中的文件名和扩展名有一个问题,但在撰写本文时,这似乎是edge的一个bug,需要修复

希望这对您可以尝试使用的人有所帮助

  • 本机JavaScript API的构造函数和
  • saveAs()
    方法

根本不需要处理任何HTML元素

var data = {
    key: 'value'
};
var fileName = 'myData.json';

// Create a blob of the data
var fileToSave = new Blob([JSON.stringify(data)], {
    type: 'application/json',
    name: fileName
});

// Save the file
saveAs(fileToSave, fileName);
如果您想漂亮地打印JSON,可以使用:

JSON.stringify(data,undefined,2)

针对那些只针对现代浏览器的用户的简单、干净的解决方案:

function downloadTextFile(text, name) {
  const a = document.createElement('a');
  const type = name.split(".").pop();
  a.href = URL.createObjectURL( new Blob([text], { type:`text/${type === "txt" ? "plain" : type}` }) );
  a.download = name;
  a.click();
}

downloadTextFile(JSON.stringify(myObj), 'myObj.json');

React:在渲染方法中需要的位置添加此选项

•处于状态的对象

<a
  className="pull-right btn btn-primary"
  style={{ margin: 10 }}
  href={`data:text/json;charset=utf-8,${encodeURIComponent(
  JSON.stringify(this.state.objectToDownload)
  )}`}
  download="data.json"
>
  DOWNLOAD DATA AS JSON
</a>
<a
  className="pull-right btn btn-primary"
  style={{ margin: 10 }}
  href={`data:text/json;charset=utf-8,${encodeURIComponent(
  JSON.stringify(this.props.objectToDownload)
  )}`}
  download="data.json"
>
  DOWNLOAD DATA AS JSON
</a>

•道具中的对象

<a
  className="pull-right btn btn-primary"
  style={{ margin: 10 }}
  href={`data:text/json;charset=utf-8,${encodeURIComponent(
  JSON.stringify(this.state.objectToDownload)
  )}`}
  download="data.json"
>
  DOWNLOAD DATA AS JSON
</a>
<a
  className="pull-right btn btn-primary"
  style={{ margin: 10 }}
  href={`data:text/json;charset=utf-8,${encodeURIComponent(
  JSON.stringify(this.props.objectToDownload)
  )}`}
  download="data.json"
>
  DOWNLOAD DATA AS JSON
</a>


类名和样式是可选的,请根据需要修改样式。

如果您更喜欢控制台代码段raser而不是文件名,则可以执行以下操作:

window.open(URL.createObjectURL(
    new Blob([JSON.stringify(JSON)], {
      type: 'application/binary'}
    )
))

您可以使用Blob轻松地自动下载文件,并在第一个param downloadJsonFile中传输它filename是要设置的文件名。

2021年的ES6+版本;也没有1MB限制:

这是改编自@maia的版本,针对现代Javascript进行了更新,已弃用的initMouseEvent替换为
新MouseEvent()
,代码总体上有所改进:

const saveTemplateAsFile = (filename, jsonToWrite) => {
    const blob = new Blob([jsonToWrite], { type: "text/json" });
    const link = document.createElement("a");

    link.download = filename;
    link.href = window.URL.createObjectURL(blob);
    link.dataset.downloadurl = ["text/json", link.download, link.href].join(":");

    const evt = new MouseEvent("click", {
        view: window,
        bubbles: true,
        cancelable: true,
    });

    link.dispatchEvent(evt);
    link.remove()
};
如果要传入对象,请执行以下操作:

const myObj = {};
const myObjAsJson = JSON.stringify(myObj);

saveTemplateAsFile(myObjAsJson);


很抱歉回来晚了。我尝试了您的答案,它确实下载了文件,但其中包含错误的数据..:(这对我有用…
data=“data:application/octet-stream;charset=utf-8,”+encodeURIComponent(JSON.stringify(data));window.open(data);
它只是以“下载”的形式下载文件但是我字符串化然后uri编码的数据是正确的。@Cybear你能解释一下第三行吗?你需要在url前加上数据:否则用户在许多浏览器中可能会达到2000个字符的限制。嘿,我知道这是一个旧的答案,但知道这个解决方案在IE(所有浏览器)上都不起作用IE不熟悉下载属性引用-感谢您的回复,即使我问这个问题已经2年了!我更喜欢纯JS而不是jQuery语法。您需要在url中预先添加数据:否则用户在许多浏览器中可能会达到2000个字符的限制。我如何在页面加载时开始下载。wHen任何用户浏览页面url时都会收到下载提示今天在Edge中的测试:data.json无法下载。这是唯一一个适用于超过=~2000个字符的数据的解决方案。因为您预先添加了数据:有人能给我指一个规范或MDN页面,详细解释整个预先添加数据类型的工作原理吗e、 “数据:text/json;字符集=utf-8”?我正在使用它,但感觉很神奇,阅读详细信息会很好,但我甚至不知道如何用谷歌搜索它。当你必须下载一个超过2000个字符的大文件时,这在IE中不起作用。但这不会无限制地起作用。你只能下载大约1MB的数据。例如,
var storageObj=[];对于(var i=0;i@YASHDAVE使用
JSON.stringify(exportObj,null,2)
instead这是一个很好的答案,
initMouseEvent()
是一种Web标准,不应该再使用了。相反,使用界面。这只是一个小的重构。@morkro是正确的;我在下面发布了一个答案,它构建并改进了@maia的答案,删除了
initMouseEvent
(代码通常已清理),saveAs()来自FileSaver.js-“根本不需要处理任何HTML元素”…阅读filesaver.js的源代码…确实如此。我的意思是,不需要直接处理HTML元素。这是最好的答案,因为它没有1MB大小限制,并且使用库而不是自定义hacksFile
const myObj = {};
const myObjAsJson = JSON.stringify(myObj);

saveTemplateAsFile(myObjAsJson);