본문 바로가기
Web Development/Javascript

[Javascript] Drag&Drop(파일 끌어다 놓기) 방식으로 파일 업로드 구현하기

by 감자맹고우 2022. 4. 8.
728x90
반응형

프로젝트를 진행하면서 파일 업로드 시 드래그앤드롭으로 처리하는 기능을 구현해야했다.

다행히, 최근에 많이 사용되는 방식이기에 구글링을 통해 쉽게 코드를 발견할 수 있었다.

 

구현을 위해 참고한 블로그는 바로 고라니 님의 블로그 글이었다.

필자의 글은 실무 내용에 가깝기에, 상세한 내용을 알고 싶다면, 해당 글을 참고하면 좋을 것 같다.

https://dev-gorany.tistory.com/254

 

 

글이 워낙 상세하게 설명되어있어, 쉽게 구현할 수 있었지만 내가 구현해야하는 프로젝트의 기능과는 차이점이 있었다.

글에서는 Drag&Drop을 하면 바로 업로드가 되는데, 나는 파일 선택까지만 진행이 되어야 했다.

파일 내용은 글을 저장할 때만 전달되어야했기에 file 내용만 바꾸는 식으로 코드를 변경해야했다.

다행히도 우리에게는 DataTransfer라는 javascript의 객체가 있었고, 글에서도 DataTransfer를 통해 처리하고 있어 쉽게 응용하여 적용할 수 있었다.

 

 

▼ DataTransfer 객체에 대한 참고를 위해 관련 내용의 글을 아래에 첨부하였다.

 

[Spring / Legacy] multiple input file을 이용한 파일 전체/부분 삭제 구현 (Javascript)

Spring Legacy 프로젝트를 진행하는 도중, 여러 개의 파일을 한번 에 추가해야 할 일이 있었다. 여러 개의 Single 파일을 한 줄씩 입력하게 하면 편했겠지만, 많은 파일을 한 번에 올릴 확률이 더 크기

devlifetestcase.tistory.com

 

반응형

 

[ 적용 방법 ]

 

우선 HTML은 유사하게 처리했다.

table 태그 안에서 파일 기능을 처리하고 있어 tr 태그와 td 태그를 사용한 것과 css나 글자 출력 부분을 제외하고는 동일하게 설정했다.

 

<!-- HTML -->
<tr>
    <td>첨부파일</td>
    <td>
        <section id="upload-section" style="width:100%; height:100%;">
            <div class="upload-box" style="width:100%; height:100%; display:table;">
                <button class="btn-upload" style="display:none;">파일선택</button>
                <input class="btn-file d-none" type="file" style="display:none;" id="testFile"/>
								
                <span id="testFileNm" style="font-size:20px; display:table-cell; vertical-align:middle;">
                    Drag&Drop
                </span>
            </div>
        </section>
    </td>
</tr>

 

 

다음은 기능 구현된 javascript 코드이다.

 

/** javascript **/

//초기화
$(document).ready(function(){
    init();
});

//파일 Drag&Drop 업로드(초기화 시 EventListener를 부여하는 방식)
const init = () => {
    const sec = document.querySelector('#upload-section');
    const btnUpload = sec.querySelector('.btn-upload');
    const inputFile = sec.querySelector('input[type="file"]');
    const uploadBox = sec.querySelector('.upload-box');
	
    //Chrome의 경우 DragOver한 파일을 Drop시 해당 파일 내용을 브라우저에 띄워주기 때문에
    //dragover와 drop 이벤트의 기본 기능을 preventDefault를 이용해 막아준다.
    
    uploadBox.addEventListener('dragover', function(e) {
        e.preventDefault();
    });
	
    uploadBox.addEventListener('drop', function(e){
        e.preventDefault();
		
        //DataTransfer로 받아올 수 있음
        const data = e.dataTransfer;
        //유효성 검사
        if(!isValid(data)) return;
		
        //파일이 있는 경우 text 교체
        $('#testFileNm').text(data.files[0] != null ? data.files[0].name : 'Drag&Drop');
        //* Drag&Drop 된 파일을 input file의 내용으로 교체
        $('#testFile')[0].files = data.files;
    });
}
	
//유효성 검사(필요한 부분만 가져와 사용하였음)
const isValid = (data) => {
		
    //파일 유효 검사
    if(data.types.indexOf('Files') < 0) return false;
    //파일 개수 검사(여러 개의 파일을 선택 후, Drag&Drop 하는 것을 방지)
    if(data.files.length > 1) {
        alert('파일은 하나씩 전송이 가능합니다.');
        return false;
    }
    return true;
    
}

 

상세 내용은 주석으로 모두 표기하였으며, 이렇게 작성하면 파일 탐색기나 폴더 등에서 파일을 upload-box에 Drag&Drop 시 파일명이 제대로 변경되어 출력되는 것을 확인할 수 있다.

 

만약 제대로 출력되지 않으면 upload-box나 상위 HTML 요소의 width나 height이 고정으로 설정되지 않아서 그럴 수 있으니 참고하면 될 것 같다.

팝업에 script를 import 하는 방식으로 적용할 때는, const 선언을 var 선언으로 바꾸는 것을 고려해야 한다.

 

아무튼, 이렇게 HTML과 JS를 작성한 후 글을 저장하고, 저장한 후 데이터를 받는 Controller에서는 기존과 동일하게 multipartfile을 통해 처리하면 서버 단으로 파일 내용이 잘 넘어가는 것을 확인할 수 있다!

 

 

▼ Controller 처리(Controller 주석 부분 참조)

 

[Spring / Legacy] Multipart multiple file의 ajax formdata를 이용한 다중 파일 업로드

multiple 속성의 File input 을 업로드하려고 하니, 문제가 발생했다. 파일을 포함한 모든 데이터를 FormData를 통해 담아서 AJAX로 서버로 전송해주는데, 아무리 받으려고 해도, 전송되는 파일 리스트의

devlifetestcase.tistory.com

 

🤞 도움이 되셨기를 바랍니다. 한 번의 클릭과 댓글은 어딘가의 누군가에게 진실로 큰 힘이 됩니다. 🐱‍🏍

 

728x90
반응형

댓글