Tistory View

javascript로 데이터를 가공한 후 다운로드를 받아야 하는 경우가 있다. 서버를 통해서 다운로드 받으면 대부분 간단히 해결이 되지만, 네트웍사용량을 줄이고 싶다든지, 이미 브라우저가 가지고 있는 내용을 다시 다운 받을 필요가 없다는 생각이 들면, 바로 다운로드하는 것이 가장 좋은 방법일 것이다.(뭐.. 솔직히 개발하는 시간 생각하면 그냥 서버에서 가공해서 받는 게, 젤 좋기는 하다..)

다운로드하는 코드

브라우저가 다운로드를 실행하게 하려면 다음과 같은 방법을 쓰면 된다.

window.location = 'data:jpg/image;base64,'+ [base64로 인코딩된 내용];

이 방법은 문제가 많은 데, 우리의 아름다운 IE는 11버전에서도 안되고, 되는 다른 브라우저도 이름을 정할 수가 없다. firefox의 경우 아름답게 길고 짜증나는 이름으로 저장이 된다.

그래서 다음과 같이 저장할 파일이름을 지정할 수 있는 방법이 있다.

function downloadURI(uri, name) {
  var link = document.createElement("a");
  link.download = name;
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  delete link;
}

downloadURI("data:text/html,[html내용]", "저장할 파일명");
downloadURI("data:image/jpeg;base64,[base64인코딩된내용]", "저장할 파일명");

순간적으로 링크를 만들어서 파일을 다운로드 할 수 있게 된다. 하지만 늘 그렇듯 우리의 아름다운 IE는 이 것도 되지 않는다. 이유는 Origin이 다르다는 이유이다. 브라우저가 접속해있는 Origin과 현재 페이지 내의 Content를 다르게 본다는 것이 좀 이상하긴..한데..

이 방식은 다른 브라우저는 잘 되니, 이제 IE에서만 되게 하면 된다.

IE10에서 다운로드

IE에서 되게하려면 navigator.msSaveBlob 변수를 통해 IE인지 먼저 구분을 하고다음의 코드를 통해 다운로드 할 수 있다.

navigator.msSaveBlob(blob, fileName);

이 방버은 IE가 10이상일 때 동작을 한다.

필자는 IE 10미만의 버전은 그냥 포기하기로 했다. 60%이상이 chrome을 쓰는 상황이기에, ie에서 안된다고 하면 다른 브라우저를 쓰라는 메세지를 뿌려주기로 했다.

이제 위의 것을을 다 묶어서 간단히 쓸 수 있는 파일을 만들어야 하는 데... 이 것을 일일이 브라우저 구분하면서 일일이 테스트하면서 만들 것을 생각하니.... 그냥 하기 싫어졌다.

하지만..

역시 이미 만들어 놓은 친구가 있다.

http://danml.com/download.html

 

download.js

Summary The download() function is used to trigger a file download from JavaScript. It specifies the contents and name of a new file placed in the browser's download directory. The input can be a String, Blob, or Typed Array of data, or via a dataURL repre

danml.com

이 곳에 가면 사용법도 잘 정리 되어 있어 그냥 쓰면된다.

 

 

download.js파일을 다음과 같이 html에 포함을 시키고

<script type="text/javascript" src="download.js"></script>

download.js
0.01MB

download함수 호출만 하면 알아서 다운로드를 할 수 있다.

download(저장할 내용변수, "저장할 파일명", "[mime-type]");

주로 다운로드가 목적이므로 mime-type은 application/octet-stream으로 지정하면 될 것이다.

 

사용법 정리

위의 사이트에 있는 사용법을 좀 정리하면.

스트링을 "dlText.txt"로 다운로드

download("hello world", "dlText.txt", "text/plain");

Uint8Array다운로드

var str= "hello world",	arr= new Uint8Array(str.length);
str.split("").forEach(function(a,b){
	arr[b]=a.charCodeAt();
});
   
download( arr, "textUInt8Array.txt", "text/plain" );

 

서버에서 파일을 받아서 다운로드(jQuery) 

이 방법은 binary데이터의 경우 문제가 발생할 수 있으니, 아래의 다른 방법으로 처리하는 것이 좋다.

$.ajax({
		url: "/download.html", 
		success: download.bind(true, "text/html", "dlAjaxCallback.html")
	});

 

base64 다운로드 : 주로 이미지를 다운받을 때

download("data:image/gif;base64,R0lGOh[~생략~]SAAOw==", "dlDataUrlBin.gif", "image/gif");

 

Ajax로 서버에서 받아와 다운로드 / base64를 이용하기에는 용량문제가 있으므로 바로 blob으로 처리한다. jQuery를 안쓰고도 간단히 처리

var x=new XMLHttpRequest();
	x.open("GET", "http://danml.com/wave2.gif", true);
	x.responseType = 'blob';
	x.onload=function(e){download(x.response, "dlBinAjax.gif", "image/gif" ); }
	x.send();

 

서버에서 그림 바로 다운로드

이 방법은 필자가 테스트를 안해봐서, 잘은 모르겠지만.. 쓸 일이 있을지도 모르겠지만, 이런 것도 있으니 일단 적어둔다.

download("/diff6.png");

 

IE9문제

IE9이하는 a태그에 download필드를 지원하지 않아서 사용할 수가 없고, dataURL을 이용하는 것도 "origin문제든가?"해서 사용할 수 없다. 사실상 서버에서 만들어 주는 방법밖에는 없다.

 

 

Replies
Reply Write