브라우저에서 JSON 객체를 파일로 다운로드


144

사용자가 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 데이터가 표시된 페이지 만 표시되며 다운로드하지는 않습니다.

나는 약간의 연구를 거쳤으며 이것이 작동한다고 주장하지만 내 코드에는 아무런 차이가 없다.

코드에 뭔가 빠졌습니까?

내 질문을 읽어 주셔서 감사합니다 :)

답변:


257

이것이 내 응용 프로그램에서 해결 한 방법입니다.

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

JS (여기서 jQuery가 아닌 순수 JS) :

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();
  }

3
이것은 ~~ 2000 자 이상의 데이터를 처리 할 수있는 유일한 솔루션입니다. 데이터를 앞에 추가 했으므로
rjurney

1
누군가이 전체 데이터 유형이 작동하는 방식, 즉 작동 방식에 대해 자세히 설명하는 사양 또는 MDN 페이지를 알려줄 수 있습니까? "data : text / json; charset = utf-8"? 나는 이것을 사용하고 있지만 마술처럼 느껴지므로 세부 사항을 읽으면 좋을 것이지만 구글에 대한 방법을 모른다.
sidewinderguy

1
2000 자 이상의 큰 파일을 다운로드해야하는 경우 IE에서는 작동하지 않습니다.
user388969

12
그러나 이것은 제한없이 작동하지 않습니다. 약 1MB의 데이터 만 다운로드 할 수 있습니다. 예를 들어 var storageObj = []; for (var i=0; i<1000000; ++i) storageObj.push('aaa');Chrome 61에서 "다운로드 실패-네트워크 오류"가 발생합니다.
oseiskar

1
@YASHDAVE JSON.stringify(exportObj, null, 2)대신 사용
TryingToImprove

40

답을 찾았습니다.

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에게 전달됩니다 **


@ Cybear 당신에게 나에게 세 번째 줄을 설명 할 수 있습니까?
Rahul Khatri

당신은 당신의 URL에 데이터를 추가하고 싶을 것입니다. 그렇지 않으면 사용자는 많은 브라우저에서 2000 자 제한에 도달 할 것입니다.
rjurney

이봐, 난 IE 다운로드 속성 참조에 익숙하지 않는이 솔루션은 IE (모두)에 작업을하지 않는 알고, 그것은 오래된 대답은 알고 있지만 - 링크
아얄 론 Grinfeld

25

이것은 순수한 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


3
이 질문을한지 2 년이 지난 후에도 답변 해 주셔서 감사합니다! jQuery 구문보다 순수한 JS를 선호합니다.
유진 유

당신은 당신의 URL에 데이터를 추가하고 싶을 것입니다. 그렇지 않으면 사용자는 많은 브라우저에서 2000 자 제한에 도달 할 것입니다.
rjurney

페이지로드시이 다운로드를 시작하려면 어떻게해야합니까? 사용자가 페이지 URL을 탐색 할 때마다 다운로드하라는 메시지가 표시됩니다.
user388969

1
Edge의 오늘 테스트 : data.json을 다운로드 할 수 없습니다.
Sarah Trees

25

당신은 시도해 볼 수 있습니다 :

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)

1
- 다른 이름으로 저장 ()는 FileSaver.js에서입니다 github.com/eligrey/FileSaver.js
Gautham

1
"아무것도 HTML 요소를 다룰 필요가 없습니다"... filesaver.js의 소스 코드를 읽는 중 ... 정확히 그렇게합니다
War

1
네. 즉, HTML 요소를 직접 처리 할 필요가 없습니다.
Gautham

3
이것은 1MB 크기 제한이없고 사용자 지정 해킹 대신 라이브러리를 사용하기 때문에 가장 좋은 대답입니다.
oseiskar

FileSaver 참조에 대해 투표권이 있습니다. 완벽하게 작동합니다.
아무도

15

다음은 나를 위해 일했습니다.

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

3
이 훌륭한 대답은하지만, initMouseEvent()A는 사용되지 않는 웹 표준과 더 이상 사용할 수 없습니다. 대신 new MouseEvent()인터페이스를 사용하십시오 . 그래도 사소한 리 팩터입니다.
morkro

10

나는 최근에 큰 형태의 모든 값의 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로 인해 버그가 수정 된 것으로 보입니다.

이것이 누군가를 돕기를 바랍니다.


Chrome에서는 작동했지만 Firefox에서는 작동하지 않는 것 같습니다. 도와주세요! codepen.io/anon/pen/ePYPJb
Urmil Parikh

1
좋은 기능, document.body.appendChild(a); a.style.display = 'none';Firefox에서 작동하도록 추가하십시오 .
Fabian von Ellerts

5

최신 브라우저만을 대상으로하는 사람들을위한 간단하고 깨끗한 솔루션 :

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

고마워, 나에게 크기 문제를주지 않은 하나
Roelant

4

download링크 의 속성은 새로운 기능이며 Internet Explorer에서는 지원되지 않습니다 ( 여기 의 호환성 표 참조 ). 이 문제에 대한 크로스 브라우저 솔루션을 위해 FileSaver.js를 살펴 보겠습니다.


2

반응 : 렌더 메소드에서 원하는 곳에 추가하십시오.

• 객체 상태 :

<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 및 스타일은 선택 사항이므로 필요에 따라 스타일을 수정하십시오.


1

다른 MIME 유형을 설정하십시오. exportData = 'data:application/octet-stream;charset=utf-8,';

그러나 저장 대화 상자에서 파일 이름에 문제가있을 수 있습니다.


늦게 와서 죄송합니다. 귀하의 답변을 시도했지만 파일을 다운로드하지만 잘못된 데이터가 포함되어 있습니다. : :(
Eugene Yu

1
이것은 나를 위해 일했습니다 ... data = "data:application/octet-stream;charset=utf-8," + encodeURIComponent(JSON.stringify(data)); window.open(data); 단순히 "다운로드"로 파일을 다운로드하지만 내가 문자열 화 한 다음 URI 인코딩 된 데이터는 그대로 있어야합니다.
제이슨 위너

0

파일 이름보다 콘솔 스 니펫, raser를 선호하는 경우 다음을 수행 할 수 있습니다.

window.open(URL.createObjectURL(
    new Blob([JSON.stringify(JSON)], {
      type: 'application/binary'}
    )
))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.