197

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

exportData = 'data:text/csv;charset=utf-8,';
exportData += 'some csv strings';
encodedUri = encodeURI(exportData);
newWindow = window.open(encodedUri);

如果客户端运行代码,它会生成空白页并开始下载 csv 文件中的数据,它工作得很好。

所以我尝试使用 JSON 对象来做到这一点

exportData = 'data:text/json;charset=utf-8,';
exportData += escape(JSON.stringify(jsonObject));
encodedUri = encodeURI(exportData);
newWindow = window.open(encodedUri);

但我只看到一个显示 JSON 数据的页面,而不是下载它。

我进行了一些研究,这个声称可以工作,但我看不出我的代码有什么不同。

我的代码中是否缺少某些内容?

感谢您阅读我的问题:)

4

13 回答 13

352

这就是我为我的应用程序解决它的方法:

HTML: <a id="downloadAnchorElem" style="display:none"></a>

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

var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(storageObj));
var dlAnchorElem = document.getElementById('downloadAnchorElem');
dlAnchorElem.setAttribute("href",     dataStr     );
dlAnchorElem.setAttribute("download", "scene.json");
dlAnchorElem.click();

在这种情况下,storageObj是您要存储的 js 对象,“scene.json”只是生成文件的示例名称。

与其他提议的方法相比,这种方法具有以下优点:

  • 无需单击任何 HTML 元素
  • 结果将被命名为你想要的
  • 不需要 jQuery

我需要这种行为而无需显式单击,因为我想在某个时候从 js 自动触发下载。

JS 解决方案(无需 HTML):

  function downloadObjectAsJson(exportObj, exportName){
    var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj));
    var downloadAnchorNode = document.createElement('a');
    downloadAnchorNode.setAttribute("href",     dataStr);
    downloadAnchorNode.setAttribute("download", exportName + ".json");
    document.body.appendChild(downloadAnchorNode); // required for firefox
    downloadAnchorNode.click();
    downloadAnchorNode.remove();
  }
于 2015-06-12T10:23:11.753 回答
45

找到了答案。

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');

似乎对我来说很好。

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

于 2013-12-03T06:02:34.307 回答
40

您可以尝试使用:

根本不需要处理任何 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'
});

// Save the file
saveAs(fileToSave, fileName);

如果您想根据这个答案漂亮地打印 JSON ,您可以使用:

JSON.stringify(data,undefined,2)
于 2017-08-09T15:28:52.270 回答
29

这将是一个纯 JS 版本(改编自牛仔版本):

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

var a = document.createElement('a');
a.href = 'data:' + data;
a.download = 'data.json';
a.innerHTML = 'download JSON';

var container = document.getElementById('container');
container.appendChild(a);

http://jsfiddle.net/sz76c083/1

于 2015-06-09T09:09:24.777 回答
21

对于那些只针对现代浏览器的人来说,简单、干净的解决方案:

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');
于 2018-06-09T09:00:44.117 回答
20

以下对我有用:

/* 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");
于 2017-01-09T17:23:27.687 回答
14

我最近不得不创建一个按钮来下载一个包含所有大型表单值的 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 的一个错误,需要修复。

希望这可以帮助某人

于 2017-04-13T09:19:05.337 回答
13

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

这是改编自 @maia 的版本,针对现代 Javascript 进行了更新,将弃用的 initMouseEvent 替换为,new MouseEvent()并且代码普遍得到了改进:

const saveTemplateAsFile = (filename, dataObjToWrite) => {
    const blob = new Blob([JSON.stringify(dataObjToWrite)], { 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()
};

如果你想传入一个对象:

saveTemplateAsFile("filename.json", myDataObj);
于 2021-01-28T14:27:48.830 回答
5

链接的download属性是新的,Internet Explorer 不支持(请参阅此处的兼容性表)。对于这个问题的跨浏览器解决方案,我会看看FileSaver.js

于 2014-08-23T00:15:05.837 回答
5
    downloadJsonFile(data, filename: string){
        // Creating a blob object from non-blob data using the Blob constructor
        const blob = new Blob([JSON.stringify(data)], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        // Create a new anchor element
        const a = document.createElement('a');
        a.href = url;
        a.download = filename || 'download';
        a.click();
        a.remove();
      }

您可以使用 Blob 轻松自动下载文件并将其传输到第一个参数 downloadJsonFile。filename是您要设置的文件的名称。

于 2020-10-14T04:24:22.593 回答
3

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>

className 和 style 是可选的,根据您的需要修改样式。

于 2018-10-02T14:53:50.397 回答
2

尝试设置另一个 MIME 类型: exportData = 'data:application/octet-stream;charset=utf-8,';

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

于 2013-11-01T06:36:14.980 回答
1

如果您更喜欢控制台片段、raser,而不是文件名,您可以这样做:

window.open(URL.createObjectURL(
    new Blob([JSON.stringify(JSON)], {
      type: 'application/binary'}
    )
))
于 2020-03-11T06:15:34.453 回答