상세 컨텐츠

본문 제목

HTML5 File API 구현

WEB/html5

by AlrepondTech 2015. 6. 22. 13:34

본문

반응형
728x170

 

 

 

 

=================================

=================================

=================================

 

 

 

 

출처: http://windbear.tistory.com/

 

[HTML5 - File Access] FILE API 를 이용해 Local File 가져오기.

HTML5 2012/03/15 17:42 바람난곰


File API 는 웹 어플리케이션에서 로컬 파일에 접근할 수 있게 해주는 Javascript API이다.
File API에 관련된 스펙은 아래와 같이 3가지가 진행되고 있다.

1. File API 
2. File API : Write 
3. File API : Directories and System 

아직 진행중이고 구현된 브라우저도 제한적이기 때문에 테스트를 위해서 최신 크롬 브라우저를 이용할 것을 강추한다.

##브라우저 지원사항 확인하기##
File API & FileReader API
Filesystem & FileWriter API


Step 1. HTML        
      

  1. <input type="file" id="inputFile" multiple="multiple"/>


먼저 type이 file인 input tag를 생성한다.
input tag가 type이 file일 경우, 자동으로 탐색기와 연결된 버튼을 생성해준다.
탐색기를 열어서 파일을 선택하면 해당 파일들의 정보를 가지고 있는 FIleList를 생성해준다.
파일을 탐색기에서 선택할 때 다수를 선택하게 할려면 multiple 속성을 주고, 한개 씩만 선택하게 할려면 빼면 된다.
      

input tag 에서 파일을 선택하게 되면 FileList 객체가 내부적으로 생성이된다. 
FileList는 File객체의 배열이다. FileList에서 File의 접근은 직접 접근외에 별다는 메소는드는 제공하지 않는다. 

아래는 스펙에서 가져온 인터페이스 정보이다. 
  

  1. interface FileList {
  2.  
  3.     getter File? item(unsigned long index);
  4.  
  5.     readonly attribute unsigned long length;
  6.  
  7. };
  8.  
  9.  
  10.  
  11. interface File : Blob {
  12.  
  13.     readonly attribute DOMString name;
  14.  
  15.     readonly attribute Date lastModifiedDate;
  16.  
  17. };
  18.  


Step 2. Javascript
      
FileList에서는 File을 찾는 것과 list의 사이즈를 제공하며, File에서는 이름과 마지막 수정 일자를 제공하는 것을 알 수가 있다. 
추가적으로 스펙에는 나와있지 않지만 크롬 브라우저에서는 파일 사이즈도 알 수가 있다.

  1. document.getElementById("inputFile").onchange=function(){
  2.  
  3.     var fileList=this.files; //input tag의 타입이 file일 경우 내부적으로 files라는 FileList 객체를 자동으로 생성합니다.
  4.  
  5.     var fileListSize=fileList.length;
  6.  
  7.     
  8.  
  9.     document.getElementById("fileListLength").setAttribute("value", fileListSize);
  10.  
  11.     var strOption='';
  12.  
  13.     for(var i=0; i<fileListSize; i++){
  14.  
  15.         var file=fileList[i];
  16.  
  17.         var fileName=file.name;
  18.  
  19.         var fileLastModifiedDate=file.lastModifiedDate;
  20.  
  21.         var fileSize=file.fileSize;
  22.  
  23.         
  24.  
  25.         strOption+='<option>'+fileName+'('+fileSize+' byte) - '+fileLastModifiedDate+'</option>';
  26.  
  27.     }
  28.  
  29.     document.getElementById("fileList").innerHTML=strOption;
  30.  
  31. };
  32.  

 
onchange 이벤트가 일어날 때 자신이 선택한 FileList를 가지고 와서 Select box에 파일 명과 사이즈를 보여주는 함수이다.

HTML5 - FILE API 를 이용해 Local File 가져오기.
[결과보기]  
[전체소스보기]  

테스트는 최신 크롬 브라우저을 권장합니다. 파폭도 정상적으로 작동하지 않내요

    

 

 

 

 

 

=================================

=================================

=================================

 

 

 

 

츌처: http://mohwaproject.tistory.com/entry/HTML5-File-API-%EA%B5%AC%ED%98%84

 

 

 

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 소스 링크:

http://jsbin.com/urupic/2

 

 

 

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

 

 

 

 

 

=================================

=================================

=================================

 

 

 

출처: http://killofki.tistory.com/144

 

1) 
이미지 관련작업을 하다보니, 여러개 이미지를 써야할 경우가 생기더라구요. 
그런데, 그런 작업을 브라우져 페이지상에서 해보려는 시도의 첫번째, DropFile 입니다. 

*주의* 
IE8 에서 작동이 안되는 것은 조금 슬프지만.. 
제가 하고싶은 작업은 canvas 에서 이미지를 가공하는 거라서요.. 

*원 출처?* http://jsfiddle.net/JtJ5N/ 
(검색으로 찾아내본 거라, 정확한지는 조금 애매하네요..) 

 

 

 



.. 

2) 


<style>
    #drop131029_1 {
        min-height: 150px;
        width: 250px;
        border: 1px solid blue;
        margin: 10px;
        padding: 10px;
    }
</style>

<h1 align=center>A File Preview Demo</h1>
<DIV id="status131029_1">Drag the files from a folder to a selected area ...</DIV>

<DIV id="drop131029_1">Drop files here.</DIV>
<DIV id="list131029_1"></DIV>

<script type="text/javascript">
    // 출처는 아마도 http://jsfiddle.net/JtJ5N/ 
 // 개조를 하긴 했는데.. 그냥 그래요.. 

(function () {
    function g(b, a, d) {
        if (b[p]) b[p](a, d, !1);
        else if (b[q]) b[q]("on" + a, d);
        else b["on" + a] = d
    }
    var p = "addEventListener",
        q = "attachEvent",
        k = "preventDefault",
        h = window,
        n = document,
        e;
    Function.prototype.bindToEventHandler = function () {
        var b = this,
            a = Array.prototype.slice.call(arguments);
        return function (d) {
            d = d || h.event;
            a.unshift(d);
            b.apply(this, a)
        }
    };
    String.prototype.r = function () {
        var b = arguments,
            a = b.length,
            d = this,
            c;
        for (c = 0; c < a; c += 2) d = d.replace(b[c], b[c + 1]);
        return d
    };
    e = function (b) {
        return n.getElementById(b)
    };
    var r, l, m;
    h.FileReader ? g(h, "load", function () {
        function b(a) {
            if (a[k]) a[k]();
            return !1
        }
        r = e("status131029_1");
        l = e("drop131029_1");
        m = e("list131029_1");
        g(l, "dragover", b);
        g(l, "dragenter", b);
        g(l, "drop", function (a) {
            a = a || h.event;
            if (a[k]) a[k]();
            var b = a.dataTransfer.files;
            for (a = 0; a < b.length; a++) {
                var c = b[a],
                    e = new h.FileReader;
                g(e, "loadend", function (a, c) {
                    var e = this.result,
                        f = n.createElement("div");
                    f.innerHTML = "Loaded : {filename} size {filesize} B".r(/{filename}/, c.name, /{filesize}/, c.size);
                    m.appendChild(f);
                    f = m.getElementsByTagName("div").length;
                    r.innerHTML = f < b.length ? "Loaded 100% of file {fileNumber} of {fileslength}...".r(/{fileNumber}/, f, /{fileslength}/, b.length) : "Done loading. processed {fileNumber} files.".r(/{fileNumber}/, f);
                    f = n.createElement("img");
                    f.file = c;
                    f.src = e;
                    m.appendChild(f)
                }.bindToEventHandler(c));
                e.readAsDataURL(c)
            }
            return !1
        })
    }) : e("status131029_1").innerHTML = "Your browser does not support the HTML5 FileReader."
})();

</script>

-- 새 창에 샘플 띄우기.. --

3) 


A File Preview Demo

Drag the files from a folder to a selected area ...
Drop files here.
 



.. 

4) 
파일탐색기..등에서 파일(들)을 "Drop file here" 라고 써있는 사각형 안으로 드롭하면, 
해당 파일의 크기와 이름..등을 표시하는 겁니다. 

*주의* 모바일에서는 사각형 표시가 안될거라 생각됩니다. <style 태그가 생략되서요.. 
*추가* 모바일에서도 표시는 되네요.. 

HTML5 에서 고시하고 있는, window.FileRead 항목이 필요하죠. 
그 후에, dropover, dropenter, drop 세가지 항목의 이벤트중 두개는 임시(?)로 받아놓고, 

drop 작업이 시작되는 이벤트를 받아, 시작하도록 되어있죠. 

순서를 그리자면, 

파일탐색기 ( 파일(들) 선택 -> 드래그 ) 
  -> 웹브라우져 drop div ( ondrop -> event.dataTransfer.files  ) // 여기까지가 drop 
  -> [] -> " window.FileReader " ( onloadend -> this.result ) // 여기는 FileRead 
  -> 결과 출력.. 

요렇겠네요. 

나중에 dropover 나 dropenter 에 대해서 조금 더 공부해봐야할 것도 같습니다. 

5) 
블로그용 내용으로 바꾸느라(?) 조금 애먹은게요, 
개인적으로는, 출력하는 내용을 규격화(?)하느라 그랬지만, (덧셈 대신 replace 를 쓰려고.. -.-..) 

원본에서는 .js 파일을 불러서 쓰는거라, 
<html onload= 이벤트는 메인페이지가 먼저 불러져있으니 감지(?)되어 쓸 수 있는 거였죠. 

하지만, one page 상에 표시해야(?)하는 저로써는 
그런 방법은 쓸 수 없어서, 

onload 가 일어나지 않던 부분을 추적해서 적용하도록 했습니다. 
(그 외에, list, status, drop ..등의 공용형태 아이디도 수정..) 

.. 

wantHate killofki@.

 

 

 

 

=================================

=================================

=================================

 

 

 

 

 

반응형
그리드형


관련글 더보기

댓글 영역