웹사이트에서는 특별한 사유가 아니면 읽기만 가능하도록 설정하는데, 그 이유는 브라우저가 사용자의 컴퓨터에 파일을 쓰게 되면 매우 위험할 수 있기 때문이다.
보통 하루에도 수 십, 많으면 수 백 페이지까지 웹을 서핑하게 되는데,
만약 파일 쓰기 기능이 있다면 어느 사이트에 접속했을 때, 바로 그 사이트가 바이러스 파일을 심어버린다면
정말 끔찍한 사태가 벌어질것이다.
<input ref={fileObserver1} type="file" onChange={onChangeFile} style= {{display: 'none'}} />
만일 여러개의 파일을 업로드 하고 싶으면 인풋박스에 multiple
을 붙이면 여러 파일을 업로드할 수 있다.
<input type="file" id="upload" multiple />
하지만 일단 우리는 하나의 파일만 업로드 할 수 있도록 하였기에
const file = e.target.files[0]
로 첫번째 파일을 가져온다.
여러 파일을 업로드 했을때는,
console.log(files); // { 0: File, 1: File, length: 2 }
이런식으로 콘솔로그를 찍어
해당 파일만 가져오자.
자, 이렇게 파일을 가져왔으니. 해당되는 파일에 대한 숨겨진 정보를 읽어야 하는데,
숨겨진 데이터를 읽으려면 FileReader API를 사용해야 한다.
window.FileReader
에 존재하기에, new FileReader()
로 파일리더를 만들어준 후 사용하자.
const reader = new FileReader();
reader.readAsDataURL(file);는
해당하는 파일을 데이터 URL로 만들어 달라는 기능이다.
처음에 콘솔로그를 찍어보면 base64라는 말로 시작하는데 이는 base64로 인코딩했다는 뜻이다.
길긴 해도 이 문자열을 주소창에 치면, 파일 정보를 주소처럼 인식한다.
즉 img 태그의 src로도 사용할 수 있다는것이다.
reader.onload = (e) => {
console.log(e.target.result)
const urls = [...fileUrl, String(e.target.result)]
setIsLocalImg(urls);
imgObserver(urls);
}
따라서 fileReader의 load 이벤트 핸들러인 onload를 사용해, 읽기 동작이 성공적으로 완료 되면 콜백함수를 통해 원하는 이벤트를 넣어줬다.
위의 콜백함수에 담긴 내용은,
url이란 배열 안에, 이전에 정의한 const [fileUrl, setFileUrl] = useState([]);
기본값인 fileUrl에 값을 복사한 후, 그것에 불러온 파일의 url을 하나씩 붙여 나가는것이다.
그리고 파일업로드 버튼은 위의 style에서 none으로 정의 했기에, ref를 사용하여 특정 버튼을 눌렀을 경우 ref가 클릭 되도록 하자.
const onClickUpload = (index) => () => {
index === 0 && fileObserver1.current.click();
index === 1 && fileObserver2.current.click();
index === 2 && fileObserver3.current.click();
}