파일업로드 시 input태그 FileList 동적으로 변경하기
파일업로드 기능을 구현하면서 겪은 문제.
사용자가 파일을 업로드하면 미리보기 형식으로 자신이 어떤 파일을 올렸는지 확인할 수 있어야 한다. 혹여 잘못 올린 파일이 있다면 해당 파일만 따로 삭제할 수 있어야 한다.
예시 :
이때 X버튼을 눌러서 화면에서 파일을 지워줘도 File Input Tag에는 그대로 해당 파일이 남아있다.
예시: 업로드한 파일 8개 중 7개를 지웠는데 화면에서는 삭제됐지만, Input창에는 그대로 남아있다.
File Input 내부적으로 files라는 FileList
를 가지고 있다.
문제는 FileList
의 값을 바꿀 수 없기 때문에 삭제된 파일을 input tag에 반영할 수 없다는 것이다. files의 값을 변경하려고 시도하면 다음과 같은 에러가 나온다.
//삭제되지 않은 파일만 files에 덮어쓰기
document.querySelector('#file-input').files =
Array.from(files).filter(file => file.lastModified !== removeTarget);
----------------------------console-------------------------------
Uncaught TypeError: Failed to set the 'files' property on 'HTMLInputElement': Failed to convert value to 'FileList'.
at HTMLDocument.<anonymous>
Javascript가 제공하는 DataTransfer
객체로 이 문제를 해결할 수 있다. MDN DataTransfer문서를 보면 Drag and drop API라고 소개한다. MDN FileList를 보면 Drag and drop할 때 FileList를 사용한다고 되어 있다.
이 DataTransfer
를 이용하여 FileList의 값을 변경할 수 있었다.
const dataTranster = new DataTransfer();
Array.from(files)
.filter(file => file.lastModified != removeTargetId)
.forEach(file => {
dataTranster.items.add(file);
});
document.querySelector('#file-input').files = dataTranster.files;
DataTransfer
가 가진 itemList
에 삭제되지 않은 파일을 필터링해서 추가하고 반환할 때는 items
가 아닌 files
를 반환해야 한다.
전체 코드
html.body
<input type="file" id="file-input" multiple />
<h3>업로드된 파일</h3>
<div id="preview">
</div>
javascript
const handler = {
init() {
const fileInput = document.querySelector('#file-input');
const preview = document.querySelector('#preview');
fileInput.addEventListener('change', () => {
console.dir(fileInput)
const files = Array.from(fileInput.files)
files.forEach(file => {
preview.innerHTML += `
<p id="${file.lastModified}">
${file.name}
<button data-index='${file.lastModified}' class='file-remove'>X</button>
</p>`;
});
});
},
removeFile: () => {
document.addEventListener('click', (e) => {
if(e.target.className !== 'file-remove') return;
const removeTargetId = e.target.dataset.index;
const removeTarget = document.getElementById(removeTargetId);
const files = document.querySelector('#file-input').files;
const dataTranster = new DataTransfer();
// document.querySelector('#file-input').files =
// Array.from(files).filter(file => file.lastModified !== removeTarget);
Array.from(files)
.filter(file => file.lastModified != removeTargetId)
.forEach(file => {
dataTranster.items.add(file);
});
document.querySelector('#file-input').files = dataTranster.files;
removeTarget.remove();
})
}
}
handler.init()
handler.removeFile()
'Study' 카테고리의 다른 글
테스트 대역 (0) | 2021.12.21 |
---|---|
@ParameterlizedTest (0) | 2021.09.08 |
[Database] Transaction, Lock (0) | 2021.05.25 |
Flyway (0) | 2021.05.16 |
인프런 Kotlin으로 개발하는 Spring Boot Web MVC - Web개론 (0) | 2021.05.15 |