개발을 하다보면, 클라이언트에 데이터가 있어서, 해당 내용을 파일로 다운로드 해야 하는 경우가 있다. 이번 포스트에서 서버와 상호 작용 없이, 간단하게 캔버스에 있는 이미지와 csv를 다운로드 하게 하는 내용을 작성하겠다.
필요한 작업은 아래와 같다.
https://developer.mozilla.org/ko/docs/Web/API/Blob
0. 데이터 준비
1. BLOB(binary large object)를 만든다.
2. Blob을 URL.createObjectURL을 사용하여, 해당 binary의 주소를 생성.
3. a태그를 이용하여, 해당 url 셋팅 하고, 다운로드.
끝이네... 간단하네.. 일단 코드! 코드를 확인 하자.
간단하게, csv파일을 다운로드 하는 것과, canvas의 이미지를 다운로드 해보자.
샘플입니다.
http://plnkr.co/edit/GZNEhOO99vgICgo9DZjJ?p=preview
위의 코드를 보면, 결국에는 util.saveAs 핵심이다.
나머지 코드는 뭐... 테스트용 코드나, 이미지에서 binary 뽑아내는 코드들이니 설명은 패스.
util.saveAs 동작을 보면.
1. A태그를 head에 생성. (한 이유는 말그대로 body가 없는 경우를 피하기 위해서? 라곤 했지만... 헤드가 없는 경우는? 이렇거나, 바디가 없는 경우가 있나? 라고 물으신다면... 헤드에 있으면 안 되는 이유라도 있나요
? 하고 묻고 싶긴 하기도 하고...)
2. 데이터로 부터 블롭 객체 생성.
3. 해당 블롭 데이터의 주소 생성.
4. 다운로드. (msSaveBlob를 쓰는 이유는 딱히 저걸로 안써도 되긴 하겠지만.... IE에서 해당 내용을 직접 제공 하는 것이기 때문에 성능이 더 좋지 않을까나? 하기도 하고. )
아 그런데... 이 코드 safari에선 안 된다.
만약에 사파리에서 저 로직을 사용 하게 하고 싶다면, A 태그 클릭을 사용자가 하게끔 하여야 합니다.
필요한 작업은 아래와 같다.
https://developer.mozilla.org/ko/docs/Web/API/Blob
0. 데이터 준비
1. BLOB(binary large object)를 만든다.
2. Blob을 URL.createObjectURL을 사용하여, 해당 binary의 주소를 생성.
3. a태그를 이용하여, 해당 url 셋팅 하고, 다운로드.
끝이네... 간단하네.. 일단 코드! 코드를 확인 하자.
간단하게, csv파일을 다운로드 하는 것과, canvas의 이미지를 다운로드 해보자.
샘플입니다.
http://plnkr.co/edit/GZNEhOO99vgICgo9DZjJ?p=preview
var util = {} function fixBinary(bin) { //binary to arrayBuffer var length = bin.length var buf = new ArrayBuffer(length) var arr = new Uint8Array(buf) for (var i = 0; i < length; i++) { arr[i] = bin.charCodeAt(i) } return buf } window.onload = function() { var canvas = document.getElementById("myCanvas") var ctx = canvas.getContext("2d") ctx.font = "30px Comic Sans MS" ctx.fillStyle = "red" ctx.textAlign = "center" ctx.fillText("Hello World", canvas.width / 2, canvas.height / 2) /** * Save As function * * @request String data, String file name, String file type (default : text/plain;charset=UTF-8) * * support browser : chrome, firefox, opera , ie edge, ie 10+ * not support browser : safari * */ util.saveAs = (function() { var a; if (!document.getElementById("fileDownload")) { a = document.createElement("a") a.id = "fileDownload" document.head.appendChild(a) //avoid no body. a.style = "display: none" } return function(data, fileName, fileType) { var binary = data try { binary = fixBinary(atob(data)); // base64 to binary to arrayBuffer } catch (e) { console.log(e); } var blob = new Blob([binary], { type: fileType || 'text/plain;charset=UTF-8' }), url = window.URL.createObjectURL(blob) if (window.navigator.msSaveBlob) { // for ie series window.navigator.msSaveBlob(blob, fileName) } else { a.href = url a.download = fileName a.click() } window.URL.revokeObjectURL(url) } }()) } var csvDownload = function() { util.saveAs(csvData, "test.csv", "application/vnd.ms-excel") } function removeHeaderBase64(base64) { return base64.substr(base64.indexOf(";base64,") + ";base64,".length) } var imageDownload = function() { var width = document.getElementById("width"); var height = document.getElementById("height"); if (+width.value > 3000) width.value = "3000" if (+height.value > 3000) height.value = "3000" if (+width.value < 0) width.value = "1" if (+height.value < 0) height.value = "1" util.saveAs(removeHeaderBase64(document.getElementById("myCanvas").toDataURL('image/jpeg')), "resized.jpeg", "image/jpeg") } var csvData = "policyID,statecode,county,eq_site_limit,hu_site_limit,fl_site_limit,fr_site_limit,tiv_2011,tiv_2012,eq_site_deductible,hu_site_deductible,fl_site_deductible,fr_site_deductible,point_latitude,point_longitude,line,construction,point_granularity\r\n" + "119736,FL,CLAY COUNTY,498960,498960,498960,498960,498960,792148.9,0,9979.2,0,0,30.102261,-81.711777,Residential,Masonry,1\r\n" + "448094,FL,CLAY COUNTY,1322376.3,1322376.3,1322376.3,1322376.3,1322376.3,1438163.57,0,0,0,0,30.063936,-81.707664,Residential,Masonry,30\r\n" + "206893,FL,CLAY COUNTY,190724.4,190724.4,190724.4,190724.4,190724.4,192476.78,0,0,0,0,30.089579,-81.700455,Residential,Wood,1\r\n" + "333743,FL,CLAY COUNTY,0,79520.76,0,0,79520.76,86854.48,0,0,0,0,30.063236,-81.707703,Residential,Wood,30\r\n" + "172534,FL,CLAY COUNTY,0,254281.5,0,254281.5,254281.5,246144.49,0,0,0,0,30.060614,-81.702675,Residential,Wood,1\r\n" + "785275,FL,CLAY COUNTY,0,515035.62,0,0,515035.62,884419.17,0,0,0,0,30.063236,-81.707703,Residential,Masonry,3\r\n" + "995932,FL,CLAY COUNTY,0,19260000,0,0,19260000,20610000,0,0,0,0,30.102226,-81.713882,Commercial,Reinforced Concrete,1\r\n"
위의 코드를 보면, 결국에는 util.saveAs 핵심이다.
나머지 코드는 뭐... 테스트용 코드나, 이미지에서 binary 뽑아내는 코드들이니 설명은 패스.
util.saveAs 동작을 보면.
1. A태그를 head에 생성. (
2. 데이터로 부터 블롭 객체 생성.
3. 해당 블롭 데이터의 주소 생성.
4. 다운로드. (
아 그런데... 이 코드 safari에선 안 된다.
만약에 사파리에서 저 로직을 사용 하게 하고 싶다면, A 태그 클릭을 사용자가 하게끔 하여야 합니다.
ie는 saveAs(blob,name) 이 있었던것 같아 보니 10까지만 이었던것 같네요 지금은 궂이 window.saveAs 체크할 필요도 없을듯..
답글삭제사파리클릭은 비디오자동재생하면서 해봤었던것 같은데 기억은 안나고 잠깐 검색해보니 아래정도.. https://stackoverflow.com/questions/8928386/jquery-trigger-click-not-working-on-safari-browsers-in-mac-ipad-iphone
답글삭제