Загрузите объект JSON в виде файла из браузера


у меня есть следующий код, чтобы пользователи могли загружать строки данных в 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, отображаемыми на ней, не загружая ее.

Я прошла некоторые исследования, и это один утверждает, что работает, но я не вижу разница в моем коде.

Я что-то упустил в своем коде?

Спасибо, что прочитали мой вопрос:)

10 86

10 ответов:

вот как я решил его для моего приложения:

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, который вы хотите сохранить, и " сцена.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();
  }

нашел ответа.

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, который является автором кода выше **

Это будет чистая версия JS (адаптированная из cowboy's):

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

для меня сработало следующее:

/* 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");

вы можете попробовать использовать:

нет необходимости иметь дело с любыми элементами 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)

на download свойство ссылок является новым и не поддерживается в Internet Explorer (см. таблицу совместимости здесь). Для кросс-браузерного решения этой проблемы я бы посмотрел на Сохранитель файлов.js

простое, чистое решение для тех, кто ориентирован только на современные браузеры:

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

попробуйте установить другой тип MIME: exportData = 'data:application/octet-stream;charset=utf-8,';

но там могут быть проблемы с именем файла в диалоге сохранения.

недавно мне пришлось создать кнопку, которая будет загружать 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','text/json');

была одна проблема с именем файла и расширением в edge, но на момент написания это казалось ошибкой с Edge, которая должна быть исправлена.

надеюсь, это поможет кому-то

реагировать добавить это, где вы хотите в вашем методе render.

• объект в состояние:

<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.props.objectToDownload)
  )}`}
  download="data.json"
>
  DOWNLOAD DATA AS JSON
</a>

имя класса и стиль являются необязательными, измените стиль в соответствии с вашими потребностями.