toggle menu

[HTML5] HTML5 File API 기초부터 썸네일 이미지 생성까지

2015. 7. 1. 19:13 HTML5


들어가며


언젠가 한번 살펴봐야지 했다가 어제서야 업무상 다른 분이 브라우저 상에서 이미지를 다룰 방법은 없는지 물어오셔서 빠르게 훑어보게 되었다.


생각했던 것보다 단순하고 깔끔하게 사용할 수 있는 방식이어서 자바스크립트에 어느정도 익숙한 개발자라면 쉽게 응용해서 원하는 목적에 맞게 활용 가능하겠다는 느낌을 받았다. 내친김에 짧게나마 사용 방법에 대해 남겨보려고 한다. 여기에서는 HTML5 File API 중 FileReader 기초부터 시작해서 간단하게 이미지의 썸네일을 만드는 것까지 살펴볼 것이다.


현재 FileReader는 거의 대부분의 브라우저에서 지원하고 있다.

http://caniuse.com/#feat=filereader




File API를 활용해서 텍스트 파일 읽기


새로운 것을 배울 때는 항상 가장 단순한 구조부터 시작해야 이해가 빠른 법이다. 아래의 텍스트 파일을 읽는 예제가 File API의 가장 기초적인 구성에 대해 이해하는데 가장 좋다는 판단이 들었다.





<pre id="preview">텍스트 파일 내용 출력 영역</pre>
<input type="file" id="getfile" accept="text/*">


HTML 태그부터 살펴보면, 단순하게 텍스트 파일의 내용을 보여줄 pre 태그 영역과, 보여줄 텍스트 파일을 선택할 input 하나로 구성되어 있다. 약간 더 눈여겨볼 만한 부분은 input 태그의 accept 속성에 text 파일만 열 수 있도록 설정했다는 점이다.



var file = document.querySelector('#getfile');

file.onchange = function () {
    var fileList = file.files ;

    // 읽기
    var reader = new FileReader();
    reader.readAsText(fileList [0]);

    //로드 한 후
    reader.onload = function  () {
        document.querySelector('#preview').textContent = reader.result ;
    };
};


자바스크립트도 크게 복잡한 부분은 없다. 먼저 input 태그를 selector 가져온 뒤, onchange 이벤트 콜백에서 처리하는 것이 전체적인 구조이다.


HTML5의 File API는 FileReader 객체를 생성하는 부분에서 시작된다. 생성한 FileReader 객체를 reader에 담은 후 readAsText 메서드를 사용해서 input으로 선택한 텍스트 파일을 읽게 된다. readAsText 를 실행이 완료되면 FileReader의 onload 이벤트가 발생되고 이 이벤트의 콜백에서 읽어들인 텍스트 파일의 내용을 삽입해주는 것으로 전체 코드가 마무리된다.


FileReader 객체를 생성해서 파일에 대한 처리를 한 뒤, 처리된 결과를 사용하는 패턴은 앞으로 살펴볼 이미지에서도 동일하니 눈에 잘 익혀두면 좋다.




File API를 활용해서 이미지 파일 읽기


이번에는 텍스트 파일이 아니라 이미지 파일을 읽어서 보여주는 예제를 살펴보자. 앞에서 살펴본 텍스트 파일을 보여주는 것과 크게 다르지 않기 때문에 예제의 소스 코드를 읽는데 큰 어려움은 없을 것이다.





<img id="preview" src="" width="700" alt="로컬에 있는 이미지가 보여지는 영역">
<input type="file" id="getfile" accept="image/*">


이번에도 HTML 태그부터 살펴보면, 동일하게 이미지 파일의 내용을 보여줄 img 태그 영역과, 보여줄 이미지 파일을 선택할 input 하나로 구성되어 있다. input 태그에서 달라진게 있다면, accept 속성에 이미지 파일만 열 수 있도록 설정한 것 정도이다.



var file = document.querySelector('#getfile');

file.onchange = function () {
    var fileList = file.files ;

    // 읽기
    var reader = new FileReader();
    reader.readAsDataURL(fileList [0]);

    //로드 한 후
    reader.onload = function  () {
        document.querySelector('#preview').src = reader.result ;
    };
};


자바스크립트 영역도 앞서 살펴본 텍스트 파일에 대한 예제와 동일한 구조인데, 이미지 파일을 다루기 때문에 몇 부분에서 차이가 나타난다. 생성한 FileReader 객체를 reader에 담은 것까지는 동일한데 파일을 읽는 메서드가 readAsText 에서 readAsDataURL 로 바뀐 것을 볼 수 있다. 평소에 Data URI Scheme 에 대해서 잘 알고 있었다면 쉽게 이해할 수 있겠지만 아닌 사람도 있을 것이다.


Data URI는 RFC 2397에 정의되어 있는 방법으로 이미지와 같은 데이터를 "data:image/png;base64,iVBORw......" 의 형태로된 URI로 표현하는 방식이다. 실제로 이미지 링크 대신 src 속성에 Data URI를 넣으면 이미지가 표시된다.


이어서 살펴보면, 텍스트 파일을 읽는 예제와 마찬가지로 이미지를 Data URI 형태로 읽어서 onload 이벤트 콜백을 통해 img 태그의 src 에 넣어줌으로써 로컬에 있는 이미지 파일을 표시하는 것으로 코드가 마무리된다. 싱거울 정도로 간단하다.




File API를 활용해서 읽은 이미지의 썸네일 만들기


이번에는 조금더 응용을 해서 로컬에서 읽어들인 이미지의 썸네일 이미지를 만드는 방법에 대해 살펴보자.





<img id="preview" src="" width="700" alt="로컬에 있는 이미지가 보여지는 영역">
<a id="download" download="thumbnail.jpg" target="_blank">
    <img id="thumbnail" src="" width="100" alt="썸네일영역 (클릭하면 다운로드 가능)">
</a>
<input type="file" id="getfile" accept="image/*">


HTML 태그 영역에서는, 동일하게 이미지 파일의 내용을 보여줄 img 태그 영역과, 보여줄 이미지 파일을 선택할 input, 그리고 추가적으로 썸네일을 보여줄 img 태그와 썸네일을 다운로드 받을 때 사용할 a 태그 정도가 추가된 것을 볼 수 있다.



var file = document.querySelector('#getfile');

file.onchange = function () {
    var fileList = file.files ;

    // 읽기
    var reader = new FileReader();
    reader.readAsDataURL(fileList [0]);

    //로드 한 후
    reader.onload = function  () {
        //로컬 이미지를 보여주기
        document.querySelector('#preview').src = reader.result;

        //썸네일 이미지 생성
        var tempImage = new Image(); //drawImage 메서드에 넣기 위해 이미지 객체화
        tempImage.src = reader.result; //data-uri를 이미지 객체에 주입
        tempImage.onload = function () {
            //리사이즈를 위해 캔버스 객체 생성
            var canvas = document.createElement('canvas');
            var canvasContext = canvas.getContext("2d");

            //캔버스 크기 설정
            canvas.width = 100; //가로 100px
            canvas.height = 100; //세로 100px

            //이미지를 캔버스에 그리기
            canvasContext.drawImage(this, 0, 0, 100, 100);

            //캔버스에 그린 이미지를 다시 data-uri 형태로 변환
            var dataURI = canvas.toDataURL("image/jpeg");

            //썸네일 이미지 보여주기
            document.querySelector('#thumbnail').src = dataURI;

            //썸네일 이미지를 다운로드할 수 있도록 링크 설정
            document.querySelector('#download').href = dataURI;
        };
    };
};


앞서 이미지를 읽는 예제와 동일하게 readAsDataURL 메서드를 사용해서 이미지를 파일을 읽은 뒤, 썸네일을 생성하기 위한 로직이 좀더 추가된 것을 볼 수 있다. 썸네일을 생성하는 기본적인 방법은 세 단계로 이루어지는데, Data URI를 이미지 객체로 변환하고, 썸네일 사이즈의 캔버스를 생성한 뒤, 이미지를 썸네일에 그리는 순서이다.


소스를 살펴보면, tempImage 를 생성하는 것이 먼저 눈에 들어온다. 캔버스가 Data URI는 받을 수 없기 때문에 Data URI 형태인 이미지를 실제 이미지 객체로 바꾸기 위해 이미지 객체를 생성해서 tempImage에 담은 것이다. 이 tempImage 의 src에 File API를 통해 읽어들인 이미지의 Data URI를 넣어주면 이 tempImage 객체에 로컬의 이미지가 담기게 된다.


tempImage에 로컬의 이미지가 담기면 onload 이벤트가 발생하는데, 이 이벤트의 콜백에서 캔버스 객체를 생성한 뒤 캔버스의 사이즈를 원하는 썸네일의 크기로 줄인 뒤에 캔버스의 drawImage 메서드를 사용해서 로컬의 이미지를 캔버스에 그리게 된다. 이 캔버스를 Document에 추가해서 보여줄 수도 있지만, 진짜 리사이즈된 이미지로 활용하기 위해서는 다시 이 썸네일 역시 Data URI 형태로 변환해주어야 한다. 그래야 img 태그에도 넣어줄 수 있고, 업로드나 다운로드도 할 수 있게 된다.


캔버스를 Data URI로 바꾸는 것은 캔버스의 toDataURL 메서드를 사용하면 쉽게 Data URI로 바꾸어줄 수 있다. 이렇게 Data URI 형태로 변환한 썸네일을 썸네일 img 태그의 src에 넣어서 썸네일을 표시해주고, a 태그의 href 에도 넣어서 이 썸네일 이미지를 다운로드도 할 수 있도록 하는 것으로 코드가 마무리된다.


a 태그를 유심히 살펴본 사람이라면 download="thumbnail.jpg" 속성이 눈에 들어왔을 것이다. a 태그의 download 속성은 다운로드할 대상의 파일명을 미리 지정해줄 수 있게 해준다. Data URI의 경우 데이터만을 가지고 있기 때문에 다운로드할 때 파일명을 지정하기 위해서 a 태그의 download 속성을 사용했다.




마치며


간단하게 HTML5의 File API, 그 중에서도 File Reader에 대해서 살펴봤다. 생각보다 단순한 구조여서 이해하는데 큰 어려움은 없었을 것이라고 생각한다.  이번 포스팅을 통해서 브라우저 상에서 파일에 접근하는 방법에 대해서 이해하고 무언가 재밌는걸 만드는 시작점이 되었기를 기대해본다.



HTML5 관련 포스팅 더보기