게시글

5만명이 선택한 평균 별점 4.9의 제로초 프로그래밍 강좌! 로드맵만 따라오면 됩니다! 클릭
강좌12 - HTML&DOM - 7년 전 등록 / 6년 전 수정

File API

이미지 미리보기

안녕하세요. 이번 시간에는 HTML5와 자바스크립트로 파일을 읽는 File API에 대해 알아보겠습니다!

파일을 읽는 김에 쓰기도 하지, 왜 읽기만 하냐고요? 브라우저가 사용자의 컴퓨터에 파일을 쓰게 되면 매우 위험할 수 있기 때문입니다. 보통 하루에도 수 십, 많으면 수 백 페이지까지 웹을 돌아다니시죠? 수 백 개의 페이지 중에는 위험한 사이트도 있을 수 있습니다. 만약 파일 쓰기 기능이 있다면 사이트에 접속했을 때, 바로 그 사이트가 바이러스 파일을 여러분의 컴퓨터에 심어버릴 수도 있겠죠?

그런데 파일 읽기가 되면, 여러분의 컴퓨터에 있는 소중한 자료들을 훔쳐보는 거 아닌가 걱정되실 수도 있겠네요. 걱정하시 마세요! 자신이 허용한 파일만 읽을 수 있습니다. 가장 쉬운 예로 파일 업로드 인풋 박스가 있죠. 인풋 박스를 누르면 파일 선택 창이 뜨는데요. 이렇게 여러분이 선택한 파일만 브라우저가 읽을 수 있습니다.

가장 흔히 하는 파일 인풋박스로 알아보죠. 자바스크립트로 선택한 후, onchange 이벤트 핸들러를 붙여, 파일을 선택할 때마다 콜백 함수가 호출되게 해줍니다. 인풋박스에 multiple을 붙이면 여러 파일을 업로드할 수 있습니다.

<input type="file" id="upload" multiple />
var file = document.getElementById('upload');
file.onchange = function(e) {
  var files = e.target.files; // FileList 객체
  console.log(files); // { 0: File, 1: File, length: 2 }
  console.log(files[0]); // 아래에 적어놨습니다.
}

위의 예시는 두 개의 사진을 올렸을 때 발생하는 이벤트입니다. e.target은 이벤트가 일어난 대상, 즉 input 자신을 가리키고요. 그 아래 files에 어떤 파일들을 올렸는지 나옵니다. 콘솔로 찍어보니 유사배열이네요. (배열처럼 생겼지만 배열은 아닌 객체입니다)

0번, 1번 키에 File 객체가 들어있습니다. File 객체는 다음과 같이 생겼습니다.

{
  name: 'zerocho.png', // 파일 이름
  size: 74120, // byte 단위 파일 크기
  lastModified:  1495791249810, // 올린 시간 timestamp
  type: 'image/png'
}

오~ 파일에 대한 정보가 들어있죠? 그런데 정작 중요한 파일 데이터 자체가 없습니다. 사실 없는 건 아니고 숨어있습니다. 이 숨어있는 데이터를 읽으려면 FileReader API를 사용해야 합니다. window.FileReader에 위치합니다. new FileReader()로 파일리더를 만들어준 후 사용하면 됩니다.

파일을 읽는 방법은 네 가지가 있습니다. readAsText, readAsDataURL, readAsArrayBuffer, readAsBinaryString이죠. 하나씩 알아봅시다. 참고로 FileReader가 즉시 파일을 읽는 게 아니기 때문에 onload 이벤트 핸들러를 붙여서 콜백으로 파일을 다 읽었다는 것을 알려주도록 해야 합니다.

readAsText

file.onchange = function(e) {
  var fileReader = new FileReader();
  fileReader.readAsText(e.target.files[0]);
  fileReader.onload = function(e) {
    console.log(e.target.result);
  }
}

undefined

네 외계어가 나옵니다. 유일하게 알아들을 수 있는 말은 처음에 나오는 png뿐이네요. 당연한 게 이미지 파일을 텍스트로 읽으라고 했으니 외계어가 나올 수밖에 없습니다. 텍스트 파일을 읽을 때 사용합시다.

readAsDataURL

file.onchange = function(e) {
  var fileReader = new FileReader();
  fileReader.readAsDataURL(e.target.files[0]);
  fileReader.onload = function(e) { 
    console.log(e.target.result);
  }
}

undefined

데이터 URL로 만드는 방법입니다. 처음에 base64라는 말이 보이시나요? base64로 인코딩했다는 뜻인데, base64로 인코딩한 경우 브라우저가 이 문자열을 인식해서 원래 데이터로 만들어줍니다. 길긴 해도 이 문자열을 주소창에 치면, 브라우저가 이 파일을 표시합니다. 즉, 파일 정보를 주소처럼 활용할 수 있다는 것이죠. img 태그의 src로도 사용할 수 있습니다.

따라서 이미지를 올리고 바로 미리보기를 표시하고 싶을 때, document.getElementById('이미지').src = e.target.result; 해주면 됩니다.

readAsArrayBuffer

file.onchange = function(e) {
  var fileReader = new FileReader();
  fileReader.readAsArrayBuffer(e.target.files[0]);
  fileReader.onload = function(e) {
    console.log(e.target.result); // ArrayBuffer 객체
  }
}

얘는 조용하게 객체 하나를 반환합니다. ArrayBuffer라는 객체인데요. 버퍼링이라고 들어보셨나요? 그것처럼 데이터를 일정한 크기로 조금 조금씩 서버로 보낼 수 있습니다. 서버로 보낼 때 사용하면 됩니다.

readAsBinaryString

file.onchange = function(e) {
  var fileReader = new FileReader();
  fileReader.readAsBinaryString(e.target.files[0]);
  fileReader.onload = function(e) {
    console.log(e.target.result);
  }
}

undefined

슬프게도 얘는 다시 외계어를 반환합니다. 이름처럼 이진 데이터를 반환하기 때문에 서버같은 곳에서 읽을 수 있습니다.

그럼 이미지 업로드를 할 때 항상 위와 같이 FileReader를 사용해서 ArrayBuffer나 BinaryString으로 해야 할까요? 아닙니다. 대부분의 경우 form의 enctype 속성을 multipart/form-data로 지정해주면 알아서 서버에 formData로 인코딩되어 넘어갑니다. 넘어간 데이터의 처리는 서버에 맡기면 됩니다!

참고로 FileReader는 File 객체 외에도 Blob이라는 Binary large object 형식의 데이터도 읽을 수 있습니다.

다음 시간에는 편하게 태그를 이동시키거나 파일을 업로드하는 Drag & Drop에 대해 알아보겠습니다!

조회수:
0
목록
투표로 게시글에 관해 피드백을 해주시면 게시글 수정 시 반영됩니다. 오류가 있다면 어떤 부분에 오류가 있는지도 알려주세요! 잘못된 정보가 퍼져나가지 않도록 도와주세요.
Copyright 2016- . 무단 전재 및 재배포 금지. 출처 표기 시 인용 가능.
5만명이 선택한 평균 별점 4.9의 제로초 프로그래밍 강좌! 로드맵만 따라오면 됩니다! 클릭

댓글

3개의 댓글이 있습니다.
3년 전
제로초! 제로초! 제로초! 제로초! 진짜 몇시간동안 헤매던거 한번에해결
6년 전
그리고, 한 참 된 글이지만 그래도 눈에 거슬려서 확인을 합니다.
예제 맨 위에 ...

\u003cinput type="file" id="upload" multiple /> \u003c--- 여기서 파일 엘리먼트를 'upload'란 아이디로 지정하셨고,

var upload = document.getElementById('upload');

이 부분이 잘못된 것 같은데

var file = document.getElementById('upload');

이라고 선언을 하셔야 아래 코드들이 동작을 할 것 같습니다.
시간 되시면 확인 부탁드릴께요 ^^*
6년 전
아하 감사합니다!
6년 전
음.. 딱 필요한 만큼 설명해 주셔서 잘 읽었습니다. Ajax를 이용한 파일 업로드를 구현하고 있는데, 업로드 전에 보여줘야 하는 부분도 많고 전처리해야 하는 부분도 많아서 걱정하고 있었는데 많은 도움이 된 것 같습니다. 고맙습니다. 책이 출간되면 꼭 사서 봐야겠네요 ^^*