*file
타입의<input>
태그와 File API를 이용해 컴퓨터에 저장된 이미지를 업로드할 수 있다. 이미지 태그 자체를 “파일선택” 버튼으로 기능하도록 할 수 있고, 라벨의 스타일을 수정하는 방식으로 “파일 선택”(파일 필드) 스타일을 변경할 수도 있다.*
업로드한 이미지는 컴포넌트 내부 상태(image)로 관리하고, 업로드 하기 전엔 기본 프로필 사진(fallbackUrl)을 표시하도록 한다.
<input>
태그의 type
을 file
로 명시하면 “파일 선택” 버튼이 표시된다. accept
속성엔 허용할 파일 유형을 .확장자
형태로 입력한다. 확장자는 대소문자를 구분하지 않는다. 여러 값을 입력할 땐 콤마 ,
로 구분한다.
특정 타입(MIME 유형)의 모든 확장자를 허용하고 싶으면 타입/*
을 입력한다. 허용하지 않은 파일 유형은 파일 선택 창에서 선택할 수 없다. (파일 유형 참고글)
.jpg, .png, .pdf
(jpg
png
pdf
파일 허용)image/*
video/*
audio/*
기본적으로 1개 파일만 선택해서 업로드할 수 있으며 multiple
속성을 true
로 설정하면 여러 파일을 업로드할 수 있다(multiple
속성을 명시하지 않으면 1개 파일만 업로드할 수 있다).
const fallbackUrl = '<https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png>';
const [image, setImage] = useState('');
const uploadHandler = () => {};
return (
// 생략
<img
src={image || fallbackUrl} // 이미지를 업로드하기 전엔 fallback 이미지 표시
alt="profile"
className="w-28 h-28 rounded-full" // Tailwind CSS 스타일
/>
<input
accept="image/jpg,image/png,image/jpeg"
type="file"
onChange={uploadHandler}
/>
)
const uploadHandler = ({ target }) => {
const file = target.files[0]; // File 객체에 선택한 이미지 파일 정보가 담김
const reader = new FileReader(); // FileReader 인스턴스 생성
// 에러없이 읽기를 마쳤을 때 onload 이벤트 호출
reader.onload = () => {
setImage(reader.result); // FileReader를 통해 DataURL로 읽은 결과(DataURL) 업데이트
};
reader.readAsDataURL(file); // FileReader API로 File 객체 읽기
};
return (
// 생략
<img
src={image || fallbackUrl}
alt="profile"
className="w-28 h-28 rounded-full" // Tailwind CSS 스타일
/>
)
<aside> 💡 File 객체는 Blob 기능을 상속받아 확장된 것으로, Blob을 사용할 수 있는 곳이면 File도 사용할 수 있다.
</aside>
“파일 선택”을 클릭해서 업로드할 파일을 선택하면 onChange
에 할당한 핸들러(uploadHandler
)가 호출된다. 선택한 파일 정보는 event.target.files
(FileList)객체에 저장되며, 파일명, 사이즈(byte), 파일 유형 등의 정보를 볼 수 있다.
FileList에 담긴 File 객체(업로드한 파일)
1개 파일만 업로드 할 수 있으므로(multiple
속성을 안줘서) 첫번째 인덱스의 files[0]
파일 정보를 불러온다. File
객체엔 선택한 파일에 대한 정보만 있을 뿐 파일 데이터는 없다. 파일 데이터를 읽으려면 FileReader API를 이용해야 한다.
const file = event.target.files[0];
new FileReader()
로 새로운 FileReader 인스턴스를 생성한다.
const reader = new FileReader();