[Spring] file input태그 하나로 파일 여러 번 업로드하기

dh·2022년 11월 20일
3

구디샵 프로젝트

목록 보기
4/5

메일을 보낼때 파일 첨부시 첨부 버튼 하나로 파일을 여러번 올릴 수 있는 것처럼 게시판에 파일 업로드를 하고 싶었습니다.

문제점

파일input 태그에 multiple 속성을 줘서 input태그 추가 없이 여러 파일을 한번에 올리고 파일 목록을 확인 하도록 했습니다.

<div>
	<input  type="file" name="files" id="files" class="files form-control form-control-sm" multiple>
</div> 
 <div class="file_drag">
     	<div class="file_list_header" style="display: none;">
     	<div class="file_list_header_task"><button type="button" class="button_svg_delete"><span class="blind">전체 삭제</span></button></div>
     	<div class="file_list_header_title"><span class="text">파일명</span></div>
        <div class="file_list_header_volume"><span class="text">용량</span><span id="fileSize">0</span></div>
 	</div>
    <ul id="fileList"></ul>
</div>

그러나 여기서 문제점이 있었는데...
input태그를 하나만 사용하니 파일 선택을 해서 올리고 다시 추가로 파일선택을 할시 기존의 선택된 파일이 덮어씌어져서 날아가는 것입니다.

이렇게 3.png파일을 올리고 로그의 FileList를 보면 3번 파일이 잘올라가 있습니다.

하지만 추가로 4,5번 파일을 선택하고 로그에서 FileList를 보면 기존의 3번 파일은 날아가고 4,5번으로 덮어씌어져서 결과적으로 4,5번만 업로드 된것을 확인할 수 있습니다.
파일선택을 다시 눌렀을 때 기존의 선택된 파일들을 유지하고 싶었습니다.

해결방법

DataTransfer 사용하기

https://developer.mozilla.org/ko/docs/Web/API/DataTransfer
https://developer.mozilla.org/en-US/docs/Web/API/FileList

FileList는 <input type="file">엘레먼트의 선택된 파일들의 목록에 접근할 수 있고 또한
Drag and Drop API사용시 드롭되는 파일의 목록에 사용된다고 합니다.
그리고 DataTransfer는 Drag and Drop할 때 드래그되고 있는 data를 유지할 때 사용한다고 나와있습니다.

따라서 DataTransfer를 이용해서 <input type="file">엘레먼트의 파일목록을 관리해보겠습니다..

	const dataTransfer = new DataTransfer();

    $("#files").change(function(){
       
        let fileArr = document.getElementById("files").files

        if(fileArr != null && fileArr.length>0){

          // =====DataTransfer 파일 관리========
            for(var i=0; i<fileArr.length; i++){
                dataTransfer.items.add(fileArr[i])
            }
            document.getElementById("files").files = dataTransfer.files;
            console.log("dataTransfer =>",dataTransfer.files
            console.log("input FIles =>", document.getElementById("files").files)
		// ==========================================
           
        }
         
    })

파일을 선택할시 dataTransfer에 저장을하고 FileList에 dataTransfer의 값을 넣어서 기존의 값을 덮어씌우지 않고 유지합니다.


3번파일을 선택하고 추가로 4,5파일을 선택하고 마지막으로 6번파일을 선택한 결과 FileList에 3,4,5,6파일이 모두 들어있는것을 확인할 수 있습니다.
업로드 결과도 모두 다 올라가 있습니다.

파일을 제거할 때도 마찬가지로 dataTransfer를 이용합니다.

 $("#fileList").click(function(event){
        let fileArr = document.getElementById("files").files
        if(event.target.className=='remove_button'){
            // console.log(event.target.dataset.index )
            targetFile = event.target.dataset.index 
            
          // ============DataTransfer================
            for(var i=0; i<dataTransfer.files.length; i++){
                if(dataTransfer.files[i].lastModified==targetFile){
                    // 총용량에서 삭제
                    total_file_size-=dataTransfer.files[i].size
                    
                    dataTransfer.items.remove(i)
                    break
                }
            }
            document.getElementById("files").files = dataTransfer.files;
     
            const removeTarget = document.getElementById(targetFile);
            removeTarget.remove();
          
            console.log("dataTransfer 삭제후=>",dataTransfer.files)
            console.log('input FIles 삭제후=>',document.getElementById("files").files)

        }
    })



3번파일 선택후 추가로 4,5,6파일을 선택하고 5번파일을 지운결과 FileList에 반영된 것을 볼수 있습니다. 업로드 결과도 3,4,6번이 잘 올라가 있습니다.

0개의 댓글