File and FileReader
해당 포스팅은 https://ko.javascript.info/file 을 공부할 목적으로 번역한 내용을 기반으로 나름대로 정리해본 포스팅입니다. 글 내의 예시코드 및 내용들을 자세히 보고 싶으시면 위의 링크 참고 부탁드립니다.
1. File
File Object 는 Blob Object 에서 확장된 개념의 객체이다. Blob 객체에 파일 시스템 관련 기능을 추가했다고 보면 된다. 즉 Blob 객체에 파일 메타데이터를 포함하고 있어 일반적으로 사용자가 선택한 파일을 나타내는데에 사용되곤 한다.
이러한 파일 객체를 얻는 방법은 2가지 정도가 있다.
- Blob 과 유사한 File Object 생성자 사용
- fileParts: Blob/BufferSource/String 값의 배열.
- fileName: 파일 이름 문자열.
- options
- lastModified: 마지막 수정 시간의 타임스탬프(정수 날짜).
new File(fileParts, fileName, [options])
<input type="file">
과 같은 브라우저 인터페이스를 통해 File Object 가져오기name
: 파일 이름lastModified
마지막 수정 시간의 타임스탬프- 주의
- input 은 여러 파일을 선택할 수 있다. 따라서 input.files는 그 파일들의 배열과 유사한 객체이다.
<input type="file" onchange="showFile(this)">
<script>
function showFile(input) {
let file = input.files[0];
alert(`File name: ${file.name}`); // e.g my.png
alert(`Last modified: ${file.lastModified}`); // e.g 1552830408824
}
</script>
2. FileReader
FileReader는 Blob(따라서 File도) 객체에서 데이터를 읽는 것이 유일한 목적인 객체이다.
이는 디스크에서 읽기 작업이 시간이 걸릴 수 있기 때문에 데이터를 이벤트를 통해 전달한다.
let reader = new FileReader(); // 인수 없음
- readAsArrayBuffer(blob): 이진 형식의 ArrayBuffer로 데이터를 읽는다.
- readAsText(blob, [encoding]): 주어진 인코딩(기본적으로 utf-8)으로 텍스트 문자열로 데이터를 읽는다.
- readAsDataURL(blob): 이진 데이터를 읽고 base64 데이터 URL로 인코딩한다.
- abort(): 작업을 취소합니다.
read* 메서드의 선택은 우리가 어떤 형식을 선호하고 데이터를 어떻게 사용할 것인지에 따라 달라진다. 즉, FileReader 객체는 파일뿐만 아니라 모든 Blob 객체를 처리할 수 있으며, 이를 이용하여 Blob을 다양한 형식으로 변환할 수 있다.
- readAsArrayBuffer: 이진 파일의 경우, 낮은 수준의 바이너리 작업을 수행할 때 사용한다. File은 Blob을 상속받기 때문에 슬라이싱과 같은 고수준 작업에 직접 호출할 수 있다.
- readAsText: 텍스트 파일의 경우, 문자열을 얻고자 할 때 사용한다.
- readAsDataURL: 이미지 또는 다른 태그의 src로 이 데이터를 사용하고자 할 때 사용한다. Blob에서 파일을 읽는 대안으로 URL.createObjectURL(file)이 있다.
읽기가 진행되는 동안 발생하는 이벤트는 다음과 같다.
- loadstart: 로딩이 시작됨.
- progress: 읽는 중에 발생.
- load: 오류 없이 읽기 완료.
- abort: abort() 호출됨.
- error: 오류 발생.
- loadend: 성공 또는 실패로 읽기 완료.
읽기가 완료되면 결과에 다음과 같이 접근할 수 있다
- reader.result: 결과 (성공한 경우)
- reader.error: 오류 (실패한 경우)
가장 널리 사용되는 이벤트는 확실히 load와 error이다. (이 2가지만 기억해도 무방)
<input type="file" onchange="readFile(this)">
<script>
function readFile(input) {
let file = input.files[0];
let reader = new FileReader();
reader.readAsText(file);
reader.onload = function() {
console.log(reader.result);
};
reader.onerror = function() {
console.log(reader.error);
};
}
</script>
웹 워커 내에서는 FileReaderSync를 사용하여 파일을 동기적으로 읽을 수 있으며, 이는 이벤트를 발생시키지 않고 결과를 반환하는 특징을 가지고 있다고도 한다.
허나 보통은 동기적으로 파일을 읽는 것은 웹 애플리케이션의 성능을 저하시킬 수 있으므로 가능한한 비동기적인 FileReader를 사용하는 것이 권장된다고 한다.
// 워커 스레드 내에서 실행되는 코드
// 파일을 동기적으로 읽기 위해 FileReaderSync 객체 생성
var fileReaderSync = new FileReaderSync();
// 파일 읽기
try {
var fileContent = fileReaderSync.readAsText(file); // 파일을 텍스트로 읽기
console.log("File content:", fileContent);
} catch (error) {
console.error("Error reading file:", error);
}
3. 정리
- File 객체는 Blob에서 상속된다.
- Blob의 메서드와 속성 외에도, File 객체는 name 및 lastModified 속성을 포함하고 있으며, 내부적으로 파일 시스템에서 읽을 수 있는 능력도 갖추고 있다. 보통은 사용자 입력(예:
<input>
또는 드래그 앤 드롭 이벤트)에서 File 객체를 얻는다. - FileReader 객체는 파일이나 블롭에서 읽을 수 있으며, 다음 세 가지 형식 중 하나로 읽을 수 있다:
- String (readAsText).
- ArrayBuffer (readAsArrayBuffer).
- Data url, base-64로 인코딩된 형식 (readAsDataURL).
- 그러나 많은 경우에는 파일 내용을 읽을 필요가 없다. Blob과 마찬가지로 URL.createObjectURL(file)을 사용하여 짧은 URL을 생성하고, 이를
<a>
또는<img>
에 할당할 수 있다. 이렇게 하면 파일을 다운로드하거나 이미지로 표시하거나 캔버스의 일부로 표시할 수 있다. - 그리고 파일을 네트워크로 보내려면, XMLHttpRequest 또는 fetch와 같은 네트워크 API는 기본적으로 File 객체를 허용한다.