본문 바로가기
Javascript study

[JS] FileReader

by 카누가 좋아요 2023. 8. 21.

📌 참고 사이트

[JavaScript]파일 입출력 - FileReader 객체 (tistory.com)

 

[JavaScript]파일 입출력 - FileReader 객체

FileReader란? FileReader는 type이 file인 input 태그 또는 API 요청과 같은 인터페이스를 통해 File 또는 Blob 객체를 편리하게 처리할 수 있는 방법을 제공하는 객체입니다. abort, load, error와 같은 이벤트에

developer-talk.tistory.com

 

자바스크립트 비동기 처리와 콜백 함수 • 캡틴판교 (joshua1988.github.io)

 

자바스크립트 비동기 처리와 콜백 함수

(중급) 중급 자바스크립트 개발자가 되기 위한 자바스크립트 비동기 처리와 콜백 함수 이해하기. 콜백 지옥과 해결 방법 등

joshua1988.github.io

 

[JavaScript]파일 업로드 구현 (tistory.com)

 

[JavaScript]파일 업로드 구현

이번 포스팅은 JavaScript에서 파일 업로드 구현하는 방법을 소개합니다. HTML input 태그 작성 html 파일에서 input 태그를 작성 후 type = 'file'로 설정하고 input 태그의 id를 지정합니다. 하나 이상의 파일

developer-talk.tistory.com

 

 

 

📋 FileReader

📍 FileReader란?

➡️ FileReader는 type이 file인 input 태그 또는 API 요청과 같은 인터페이스를 통해 File 또는 Blob 객체(파일류의 불변하는 미가공 데이터)를 편리하게 처리할 수 있는 방법을 제공하는 객체이다.

 

➡️ abort (리소스의 로딩이 중단되었을 때), load, error와 같은 이벤트에서 발생한 프로세스를 처리하는데 주로 사용된다.

 

➡️ FileReader 객체는 File 또는 Blob 객체를 읽어서 result 속성에 저장한다.

 

 

📍 FileReader는 비동기로 동작한다

❓ 비동기 처리

JS에서의 비동기 처리는 특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 JS의 특성 중 하나이다.

 

ex) setTimeOut 함수

 

console.log('Hello');

setTimeout(function() {
  console.log('Bye');
}

console.log('Hello Again');

 

위의 코드의 실행 결과는 Hello가 출력된 다음 Hello Again이 출력되고, 3초가 지나면 'Bye'가 출력되는 것이다. 즉, setTimeOut 함수는 비동기 방식으로 실행된다.

Hello가 출력되고 3초 뒤에 'Bye'가 출력되고 마지막으로 Hello Again이 출력되는 것이 아니다.

console.log('Hello')를 실행한 뒤 setTimeout 함수를 일단 실행하고 나서 바로 console.log('Hello Again')으로 넘어간 것이다. 

setTimeout 에 설정한 시간인 3초를 console.log('Hello Again')이 기다려 주지 않는다.

 

 

➡️ FileReader비동기로 동작하여 HTML 페이지 렌더링 차단을 피할 수 있게 된다.

(만약 FileReader가 동기적으로 작동한다면 대용량인 파일을 선택하였을 때 그 파일 정보를 result 속성에 저장할 때까지 HTML 렌더링이 늦어지게 되는 영향을 미칠 수 있다. 따라서 비동기 방식으로 작동한다.)

 

 

 

📋 FileReader 사용하기

📍 FileReader 객체 생성하기

new 연산자를 이용하여 생성할 수 있다.

 

// FileReader 객체 생성
let fr = new FileReader();

 

 

📍 파일 읽기

아래의 함수들 중 하나를 호출하여 File 또는 Blob를 읽어서 FileReader의 result 속성에 저장할 수 있다.

아래 함수들은 파일을 어떤 방식으로 읽을지를 결정하는 함수들이다.

 

// 인자를 텍스트로 읽음. result 속성에 파일의 내용이 문자열 값으로 들어감.
fr.readAsText(File 또는 Blob);
 
// 인자를 읽은 후 데이터 URL 표현으로 변환한다.
fr.readAsDataURL(File 또는 Blob);

// 인자를 배열 버퍼로 읽음.
fr.readAsArrayBuffer(File 또는 Blob);

// 인자를 비트 문자열로 읽음.
fr.readAsBinaryString(File 또는 Blob);

 

 

📍 파일을 읽은 결과를 처리하기 위한 과정

아래와 같은 이벤트에서 FileReader 객체를 사용하여 객체를 읽은 결과를 확인하거나 처리가 가능하다.

 

➡️ load

파일 읽기 작업이 완료되면 작동한다.

➡️ error

에러로 인해 파일을 읽을 수 없을 때 작동한다.

➡️ abort

abort() 함수를 호출하여 파일 읽기 작업이 취소될 때 작동한다.

➡️ progress

파일을 읽는 동안 일정한 간격으로 동작한다.

 

 

📍 FileReader 객체의 주요 속성

FileReader 객체의 가장 핵심적인 속성으로 다음과 같은 것들이 있다.

 

➡️ result

파일을 읽은 결과를 가지고 있거나 null이다.

 

➡️ error

파일 읽기 작업에서 발생한 오류를 설명하는 Error 객체를 가지고 있거나 null이다.

 

➡️ readyState

FileReader 객체의 상태를 아래와 같이 숫자로 관리한다.

0 : 비어있음. 즉, FileReader 객체에서 읽기 작업이 수행되지 않았음.

1 : 로딩 중 (파일을 읽는 중)

2 : 파일 읽기 작업이 완료됨.

 

 

 

📋 FileReader 사용 예제

우선 HTML에서 type이 file인 input 태그를 작성한다.

* 하나 이상의 파일을 업로드하는 것을 원하면 multiple 속성에 'multiple' 값을 넣어주면 된다. (파일 선택 시 Ctrl 키나 Shift 키를 누른 상태에서 여러 개를 선택해야 한다.)

* accept 속성을 사용하면 특성 파일 확장자만을 허용하게 할 수도 있다.

 

<!DOCTYPE html>
<html lang="en">
  ..........
  <body>
    <input type="file" id="file" />
  </body>
</html>

 

이제 JS에서 이벤트 핸들러를 이용해 파일을 선택하거나 변경하였을 때 실행될 함수를 구현해 보자.

이것과 관련된 이벤트는 onchange 이벤트이다.

 

const fileInput = document.querySelector("input");
console.log(fileInput.files);     
// FileList 반환, 길이 0 (아무것도 없음)

fileInput.onchange = () => {
  console.log(fileInput.files);     
  // FileList 반환, 길이 1, 0번째에 선택한 파일에 대한 정보가 담김.

  const selectedFile = fileInput.files[0];
  console.log(selectedFile);     
  // 아까 FileList에서 0번째 요소(파일에 대한 정보) 출력
};

 

파일을 하나 선택하면 fileInput의 files 프로퍼티에 해당 파일에 대한 정보가 담기게 된다.

그것은 FileList 형태로 되어 있는데, 우리는 하나만 선택하였으므로 fileInput.files의 0번째 요소가 바로 우리가선택한 파일의 정보가 된다. (파일을 여러 개 선택한 경우 FileList의 길이가 선택한 파일의 개수만큼 되고, 0번째 요소는 첫번째로 선택한 파일에 관한 정보이다.)

 

selectedFile에 할당된 우리가 선택한 File 객체를 열어보면 여러 가지 속성들이 존재한다.

➡️ name : 파일 이름 (읽기 전용)

➡️ size : 파일의 크기 (읽기 전용)

➡️ type : 파일의 MIME 유형, 알 수 없는 경우 빈 문자열 (읽기 전용)

* MIME 유형 : 클라이언트에게 전달된 문서의 유형 (웹에서 그냥 파일 확장자는 별 의미가 없다.)

 

이제 선택한 파일을 브라우저 화면에 보여주는 작업을 진행하겠다.

선택한 파일을 읽어 URL 표현으로 바꾸어 그 내용을 img 태그의 src 속성에 반환하여 보여줄 수 있다.

앞서 배웠듯이, FileReader 객체를 생성하여 readAsDataURL 메서드를 사용해 선택한 파일을 읽어 URL 표현으로 변환하고, img 태그를 생성하여 그것의 src 속성으로 넣어서  문서의 body 안에 넣어주면 된다.

 

// input(type이 file인) 노드 가져오기
const fileInput = document.querySelector("input");

// 파일을 선택하거나 변경하는 이벤트가 일어났을 때 아래 함수 실행
fileInput.onchange = () => {
  // 선택한 파일의 정보는 fileInput의 files 프로퍼티의 0번째에 들어 있음.
  const selectedFile = fileInput.files[0];

  // 새로운 FileReader 객체 생성
  const fileReader = new FileReader();
  // 내가 선택한 파일을 읽어서 URL의 형태로 변환
  fileReader.readAsDataURL(selectedFile);

  // FileReader가 파일을 읽는 동작을 성공적으로 마쳤을 때(onload 이벤트) 아래 함수 실행
  fileReader.onload = () => {
    // 이미지 태그 생성
    const newImg = document.createElement("img");
    // 이미지 태그의 src 속성값으로 fileReader의 결과값 fileReader.result를 넣어줌. (이미지 url)
    newImg.src = fileReader.result;
    // body에 이미지 태그 추가해 줌.
    document.body.appendChild(newImg);
  };
};

 

아래와 같이 동작하면 성공한 것이다. (파일을 선택하는 모습은 영상에 보이지 않는데, png 파일 하나를 선택한 것이다.)

 

 

 

💡 readyState에 대하여 위 예제로 살펴보자.

 

const fileInput = document.querySelector("input");

fileInput.onchange = () => {
  const selectedFile = fileInput.files[0];

  const fileReader = new FileReader();
  // FileReader 객체 생성 직후
  console.log(fileReader.readyState);     // 0 (읽기 작업 안함)
  
  fileReader.readAsDataURL(selectedFile);
  // FileReader가 seletedFile 읽기 시작한 직후
  console.log(fileReader.readyState);     // 1 (읽는 중)

  fileReader.onload = () => {
    // FileReader가 seletedFile을 성공적으로 읽은 후
    console.log(fileReader.readyState);     // 2 (읽기 완료)
  };
};

댓글