Spring Legacy 프로젝트를 진행하는 도중, 여러 개의 파일을 한번 에 추가해야 할 일이 있었다.
여러 개의 Single 파일을 한 줄씩 입력하게 하면 편했겠지만, 많은 파일을 한 번에 올릴 확률이 더 크기 때문에 Multiple 속성 ( '<input type="file" id="file" multiple>' ) 으로 구현하였다.
그러다보니 예상치 못한 문제에 부딪혔었는데, 부딪혔던 문제와 해결 방법을 기록으로 남겨 공유하고자 한다.
※ File 타입의 Input은 반드시 알아두어야 할 점이 있다.
value 값을 사용자가 선택하는 것 외에 임의적으로 입력할 수 없도록 되어 있다는 점이다.
생각해보자.
코드에서 파일을 직접 입력할 수 있다면 보안 이슈가 아주 쉽게 발생하게 될 것이다.
그러니 input 밖에서 파일을 따로 처리하고 싶다면, 사용자에게 입력받은 파일을 변수에 할당하여 처리하면 된다.
const files = $('#file')[0].files;
1. 파일 전체 삭제
전체 삭제는 간단하다. File Input의 value 값을 초기화 하면 된다.
const deleteAll = () => {
$('#file').val('');
}
2. 파일 개별 삭제
multiple 속성의 File Input은 사용자에게 입력받은 값을 FileList로 처리한다.
FileList는 Array와는 다르지만, Array로 처리할 수 있다.
그렇기 때문에 FileList를 Array로 처리하기 위해 Array.from을 사용하였고,
( https://stackoverflow.com/questions/3144419/how-do-i-remove-a-file-from-the-filelist/3162319 )
Array를 FileList로 처리하기 위해 Javscript가 제공하는 DataTransfer 객체를 이용하였다.
( https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer )
const delete = (fileNum) => { //fileNum은 li 의 index 값
const dataTransfer = new DataTransfer();
let files = $('#file')[0].files; //사용자가 입력한 파일을 변수에 할당
let fileArray = Array.from(files); //변수에 할당된 파일을 배열로 변환(FileList -> Array)
fileArray.splice(fileNum, 1); //해당하는 index의 파일을 배열에서 제거
fileArray.forEach(file => { dataTransfer.items.add(file); });
//남은 배열을 dataTransfer로 처리(Array -> FileList)
$('#file')[0].files = dataTransfer.files; //제거 처리된 FileList를 돌려줌
}
이렇게 하고, console.log(files)를 찍어 보면 FileList 가 제대로 삭제 처리 되고 있음을 알 수 있다 !
================================= 2022.12.05 추가 =================================
p.s. DOM 요소 index 찾는 방법 추가 ( 현재 요소가 몇 번째인지 찾는 방법 )
// 개별 파일의 삭제 버튼에 적용할 메소드
const delete = (obj) => {
//현재 버튼(obj)의 상위 요소 중 가장 가까운 div 요소를 찾음
//div는 선택한 파일 목록을 보여주는 부분
const div = $(obj).closest('div');
//div에서 'button' 태그 중 현재 버튼(obj)의 index가 몇 번째인지 확인
//0부터 시작
const index = div.find('button').index(obj);
~~~ 이하 부분 처리는 동일 ~~~
}
🤞 도움이 되셨기를 바랍니다. 한 번의 클릭과 댓글은 어딘가의 누군가에게 진실로 큰 힘이 됩니다. 🐱🏍
댓글