HTML5 File API 구현
HTML5 File API 구현
웹 브라우저(Gecko, Webkit 등..)상에서 로컬 영역의 특정 파일을 접근, 조작할 수 있는 여러가지 방법을 제공합니다.
단 제공되는 File Interface는 로컬 보안 상 파일 탐색기 또는 Drag & Drop 방식을 이용해 사용자가 직접 선택한 File로 한정 시킵니다.
아래는 관련 소스를 모듈화 시킨 코드이며, 각 기능은 아래와 같습니다.
1. 생성자 함수:
File(form || undefined)
form: 해당 File 컨트롤을 포함하는 부모 엘리먼트(보통 Form 엘리먼트가 해당됨)
2. 각 File 컨트롤의 onchange 이벤트 등록
.change(callback);
callback: onchange 이벤트 시 핸들러
3. 각 Drop Zone 엘리먼트의 dragenter 이벤트 등록
.dragenter(elems, callback)
elems: 엘리먼트 or 엘리먼트 배열
callback: ondragenter 이벤트 시 핸들러
4. 각 Drop Zone 엘리먼트의 dragleave 이벤트 등록
dragleave(elems, callback)
elems: 엘리먼트 or 엘리먼트 배열
callback: dragleave 이벤트 시 핸들러
5. 각 Drop Zone 엘리먼트의 dragover 이벤트 등록
dragover(elems, callback)
elems: 엘리먼트 or 엘리먼트 배열
callback: dragover 이벤트 시 핸들러
6. 각 Drop Zone 엘리먼트의 dragdrop 이벤트 등록
dragdrop(elems, callback)
elems: 엘리먼트 or 엘리먼트 배열
callback: dragover 이벤트 시 핸들러
7. progress 관련 이벤트 등록
progress(data, before, update, load, dataType)
data: file 객체
before: 읽어드린 file 객체의 onloadstart 이벤트 시 핸들러
update: 읽어드린 file 객체의 onprogress 이벤트 시 핸들러
load: 읽어드린 file 객체의 onload 이벤트 시 핸들러
dataType: file 객체의 저장 데이터 타입
8. file 객체 반복자
File.each(files, callback, type)
files:컨트롤을 통해 선택된 파일 리스트
callback: 각 컨트롤의 반복자 callback
type: 허용 file 타입
9. 파일 읽기
Fil.read(data, callback, dataType)
data: 읽어드릴 file 객체
callback: 읽어드린 file 객체의 onload 이벤트 시 핸들러
dataType: file 객체의 저장 데이터 타입
10. Blob 생성
File.readBlob(data, start, end, callback)
data: 읽어드릴 file 객체
start: 시작 바이트 배열 index
end: 마지막 바이트 배열 index
callback: 읽어드린 file 객체의 onload 이벤트 시 핸들러
- 관련된 자세한 소스는 아래 jsbin.com에 등록된 페이지를 살펴 보시기 바랍니다.
1. JSBin 소스 링크:
2. 모듈 사용방법:
window.onload = function (e) { //var target = document.getElementById('spin'); //var spinner = new Spinner(opts).spin(target); var zone1 = document.getElementById('drop_zone1'); var zone2 = document.getElementById('drop_zone2'); var zone3 = document.getElementById('drop_zone3'); var zones = [zone1]; var progress = document.getElementById('progress_bar'); var progress_percent = document.getElementById('progress_percent'); File().change(function (e, files) { zone1.innerHTML = "Loading..."; var that = this; var h = []; File.each(files, function (idx) { File.read(this, function (e, result) { var html = '<li>'; html += '<div style="margin-top:20px;margin-left:10px;">'; html += '<img src="' + result + '" width="200" height="200" style="border:gray 2px solid" />'; html += '<div style="margin-top:10px"> name: ' + escape(this.name) + ' type: ' + this.type + ' size: ' + this.size + ', lastModifiedDate: ' + this.lastModifiedDate + ',' + this.lastModifiedDate.toLocaleDateString() + '</div>'; html += '<textarea style="margin-top:10px;width:600px;height:200px">' + result + '</textarea>'; html += '</div>'; html += '</li>'; h.push(html); if (idx >= files.length - 1) document.getElementById('image_list').innerHTML += h.join(''); }, 'dataUrl'); /* File.readBlob(this, 0, this.size, function (e, result) { }); */ that.progress(this, function (e) { progress_percent.style.width = '0%'; progress_percent.textContent = '0%'; progress.className = 'loading'; }, function (e, loaded, total) { var percent = Math.round((loaded / total) * 100); if (percent < 100) { progress_percent.style.width = percent + '%'; progress_percent.textContent = percent + '%'; } }, function (e) { progress_percent.style.width = '100%'; progress_percent.textContent = '100%'; if (idx >= files.length - 1) { zone1.innerHTML = "Upload Complete"; window.setTimeout(function () { progress.className = ''; }, 2000); } }); }, 'image'); }) .dragenter(zones, function (e, zone) { zone.style.backgroundColor = 'orange'; zone.style.color = 'black'; }) .dragover(zones, function (e, zone) { zone.style.backgroundColor = 'orange'; zone.style.color = 'black'; }) .dragleave(zones, function (e, zone) { zone.style.backgroundColor = 'white'; zone.style.color = '#BBB'; }) .dragdrop(zones, function (e, files, zone) { zone.innerHTML = "Loading..."; var that = this; var h = []; File.each(files, function (idx) { File.read(this, function (e, result) { var html = '<li>'; html += '<div style="margin-top:20px;margin-left:10px;">'; html += '<img src="' + result + '" width="200" height="200" style="border:gray 2px solid" />'; html += '<div style="margin-top:10px"> name: ' + escape(this.name) + ' type: ' + this.type + ' size: ' + this.size + ', lastModifiedDate: ' + this.lastModifiedDate + ',' + this.lastModifiedDate.toLocaleDateString() + '</div>'; html += '<textarea style="margin-top:10px;width:600px;height:200px">' + result + '</textarea>'; html += '</div>'; html += '</li>'; h.push(html); if (idx >= files.length - 1) document.getElementById('image_list').innerHTML += h.join(''); }, 'dataUrl'); /* File.readBlob(this, 0, this.size, function (e, result) { }); */ that.progress(this, function (e) { progress_percent.style.width = '0%'; progress_percent.textContent = '0%'; progress.className = 'loading'; }, function (e, loaded, total) { var percent = Math.round((loaded / total) * 100); if (percent < 100) { progress_percent.style.width = percent + '%'; progress_percent.textContent = percent + '%'; } }, function (e, result) { progress_percent.style.width = '100%'; progress_percent.textContent = '100%'; if (idx >= files.length - 1) { zone.style.backgroundColor = 'white'; zone.style.color = '#BBB'; zone.innerHTML = "Upload Complete"; window.setTimeout(function () { progress.className = ''; }, 2000); } }); }, 'image'); }); } function bind(elem, type, handler, capture) { type = typeof type === 'string' && type || ''; handler = handler || function () { ; }; if (elem.addEventListener) { elem.addEventListener(type, handler, capture); } else if (elem.attachEvent) { elem.attachEvent('on' + type, handler); } return elem; };
3. 실행화면 및 브라우저 지원 상황:
- 브라우저 지원 상황:
http://caniuse.com/#feat=fileapi
5. 참고 사이트:
[HTML5강좌] 20. File API:
http://sqler.pe.kr/OSS/bIISLec/402253
Html5rocks File API:
http://www.html5rocks.com/en/tutorials/file/dndfiles/
W3c File API:
http://www.w3.org/TR/FileAPI/#dfn-Blob