소통하는 개발자 Sean
article thumbnail

파일 선택창을 통해 파일을 업로드 할 수도 있고, 

파일의 드래그 앤 드롭을 통해 파일을 업로드 할 수 있다.

선택창과 드래그 앤 드롭을 혼합하여 여러개의 파일을 보낼 수도 있어야 한다.

프로젝트를 하면서 겪은 문제는 "드래그 앤 드롭"을 사용했을 때 file이 서버로 전달되지 못했던 것이다.

 

문제가 되었던 코드를 순차적으로 살펴보자. 

input type='file'에 드래그앤 드롭 파일 추가해서 서버로 넘기기 (실패)

파일 선택창을 통해 파일을 선택하면 input type='file'을 통해 파일이 들어가기 때문에

name="files"이  위에 보이는 post-register의 files 파라미터로 매핑이 된다.

드래그앤 드롭으로 파일을 등록하면 input type='file'에 value로 등록되지 않는 문제가 있다.

여기서 하나의 아이디어를 생각했는데, input type='file'의 value 값을 마음대로 조정할 수 있다고 가정하자.

파일 선택창 + 드래그 앤 드롭으로 얻은 파일들을 모두 파일 변수 배열(postFiles)에 넣는다.

그리고 마지막 submit시에 <input type='file' name='files'>의 value에 파일 변수 배열을 다 넣는다면,

post-register의 files 파라미터로 매핑이 되면서 파일을 AWS S3에 등록할 수 있을것이다.

 

 

좋은 아이디어라고 생각하고 실천에 옮기면 이와같은 오류를 만나게 된다.

코드 - $('input[type="file"]').val(null).val(sel_files)

오류 -  jquery2.2.4.min.js:4 Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string. 

 

chatGPT에게 물어보니 다음과 같은 답변을 해준다.

보안상의 문제라고 하니 다른 해결방법을 찾아보도록 하자...

 

FormData를 활용한 드래그앤 드롭 파일 추가해서 서버로 넘기기 (실패)

$('input[type="file"]').val(null).val(sel_files)이 보안상의 문제로 안되는 것을 깨달았으니

form의 FormData를 만들어서 서버로 전달하기로 했다.

이부분에서도 시간을 많이 소요했는데,

제일 먼저 'new FormData(form[0])' 부분이다.

만약 'new FormData(form)' 으로 했다면 아래와 같은 에러를 만나게된다.

Failed to construct 'FormData': parameter 1 is not of type 'HTMLFormElement'.

 

FormData 생성자에는 DOM요소를 주어야하는데 'form'은 jQuery 객체이지 DOM요소가 아니다.

그래서 'form[0]'을 사용하면 jQuery 객체에서 첫 번째 DOM 요소를 가져올 수 있기 때문에 에러가 나지 않는다.

$('#form').submit(function (e) {
    let form = $(this);
    let formData = new FormData(form[0]);

    for (let i = 0; i < sel_files.length; i++) {      
        formData.append('uploadFiles[]', sel_files[i]);
        formData.append('uploadFiles', sel_files[i]);
    }    
})

jQuery를 사용해서 form 태그를 가져온다음, 전송할 데이터를 추가로 넣어준다.

'uploadFiles[]' 와 'uploadFiles'를 둘 다 만들었는데, 서버로 전달 할 때

'uploadFiles'가 아닌 ' uploadFiles[]'를 사용해야 서버가 받아준다는 글을 보고 두개다 테스트 중이였다.

(어차피 컨트롤러에서 둘 중 하나만 매핑이 되면 되는거니까..)

위의 jQuery코드로 서버에 전송하면 에러가 발생한다.

에러 내용은 - uploadFiles가 null값으로 들어온다는 에러이다.

이 부분에서 많은 시간을 소요했는데,

view 단에서 formData를 통해서 전송할 때는 ajax를 통해서 전송을 해야 정상적인 통신이 가능하다.

결론은 uploadFiles에 매핑이 안되서 ajax를 사용해야 한다.

(정말 많은 시도를 해본결과 얻은 결론이다, 혹시 formData를 ajax를 사용하지 않고 서버로 전송할 수 있는 방법을 알고 계신다면 댓글이나 메일 주시면 감사의 마음으로 커피 사례를 하려고 한다 ㅠㅠ)

 

 

FormData를 활용한 드래그앤 드롭 파일 추가해서 서버로 넘기기 (성공)

선택한 파일을 모은 postFiles를 append 해준다음, ajax로 요청하면 된다.

@ResponseBody를 사용하지 않고 ajax에서 dataType : 'text'로 대체했다.

 

이렇게 "드래그 앤 드롭"을 사용했을 때 file이 서버로 전달되지 못했던 문제를 위의 코드로 겨우 해결하였다.

처음엔 쉽게 해결할 줄 알고 집중 안하고 이것저것 해보다가 5시간 정도를 소요한것 같다..

profile

소통하는 개발자 Sean

@Sean-creative

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!