본문 바로가기
프로그래밍/JavaScript

Javascript 파일업로드 input 태그 multiple 사용시 FileList 동적으로 변경하기

by so5663 2023. 1. 8.

form 태그에서 multiple로 파일 업로드 구현

<form name="fileForm" action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" id="file-input" multiple />
    <h3>업로드된 파일</h3>
    <div id="preview"></div>
</form>

예시 화면에서는 파일을 삭제해도 input창에는 그대로 남아있습니다.

 

콘솔 창으로 확인 결과

File Input 내부적으로 files라는 FileList를 가지고 있었습니다.

여기서 문제는 html은 삭제를 해도 FileList 즉 input tag에는 삭제가 되지 않았습니다.

 

검색 결과

Javascript가 제공하는 DataTransfer 객체로 이 문제를 해결할 수 있다고 합니. MDN DataTransfer문서를 보면 Drag and drop API라고 소개되어 있습니다. MDN FileList를 보면 Drag and drop할 때 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를 반환해야 함

 

자바스크립트 전체 소스

        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()