Untitled

*file 타입의 <input> 태그와 File API를 이용해 컴퓨터에 저장된 이미지를 업로드할 수 있다. 이미지 태그 자체를 “파일선택” 버튼으로 기능하도록 할 수 있고, 라벨의 스타일을 수정하는 방식으로 “파일 선택”(파일 필드) 스타일을 변경할 수도 있다.*

기본 구조


업로드한 이미지는 컴포넌트 내부 상태(image)로 관리하고, 업로드 하기 전엔 기본 프로필 사진(fallbackUrl)을 표시하도록 한다.

<input> 태그의 typefile로 명시하면 “파일 선택” 버튼이 표시된다. accept 속성엔 허용할 파일 유형을 .확장자 형태로 입력한다. 확장자는 대소문자를 구분하지 않는다. 여러 값을 입력할 땐 콤마 , 로 구분한다.

특정 타입(MIME 유형)의 모든 확장자를 허용하고 싶으면 타입/* 을 입력한다. 허용하지 않은 파일 유형은 파일 선택 창에서 선택할 수 없다. (파일 유형 참고글)

기본적으로 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}
  />
)

업로드 핸들러 — File 객체 / FileReader API


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 스타일
  />
)

File 객체

<aside> 💡 File 객체는 Blob 기능을 상속받아 확장된 것으로, Blob을 사용할 수 있는 곳이면 File도 사용할 수 있다.

</aside>

“파일 선택”을 클릭해서 업로드할 파일을 선택하면 onChange에 할당한 핸들러(uploadHandler)가 호출된다. 선택한 파일 정보는 event.target.files (FileList)객체에 저장되며, 파일명, 사이즈(byte), 파일 유형 등의 정보를 볼 수 있다.

FileList에 담긴 File 객체(업로드한 파일)

FileList에 담긴 File 객체(업로드한 파일)

1개 파일만 업로드 할 수 있으므로(multiple 속성을 안줘서) 첫번째 인덱스의 files[0] 파일 정보를 불러온다. File 객체엔 선택한 파일에 대한 정보만 있을 뿐 파일 데이터는 없다. 파일 데이터를 읽으려면 FileReader API를 이용해야 한다.

const file = event.target.files[0];

FileReader API

new FileReader()로 새로운 FileReader 인스턴스를 생성한다.

const reader = new FileReader();