jquery 드래그 앤 드롭 파일 업로드

2018. 4. 25. 13:48language/jquery


드래그 앤 드롭 파일 업로드

 

jquery 를 활용하여  드래그 앤 드롭 멀티 파일 업로드 기능을 구현해 보자

 

 

 

요즘 홈페이지들을 보면 파일을 업로드 할 때 예전처럼 파일탐색창에서 선택하여 업로드 할수도 있지만

 

컴퓨터에 있는 파일을 마우스로 드래그해서 브라우저에 드랍하면 파일이 업로드 되는 기능을 자주 만날 수 있다.

 

구현하는 방식은 여러가지가 있을 거라고 생각이 된다.

 

본 포스팅에서는 jquery 를 활용하여 드래그 앤 드롭 기능을 구현해 보자.

 



 

설명 :

 

jquery 의 드롭 이벤트 dragenter, dragleave, dragover, drop 을 파일이 드롭될 특정 영역(태그)에 설정한다.

 

dragenter : 드래그 요소가 특정 영역에 들어갔을 경우 호출

dragleave : 드래그 요소가 특정 영역에서 벗어났을 경우 호출

dragover : 드래그 요소가 특정 영역에 있을 경우 호출

drop : 드래그 요소가 드롭되었을 경우 호출

 

위 4개의 이벤트 중 파일이 드롭되었을 경우에 drop 이벤트가 호출되며

 

이때 파일 Object를 javascript 영역에서 가지고 있다가

 

ajax를 활용하여 비동기 방식으로 전송하면 된다.

 

당연히 jquery 를 import 한 후 사용하여야 한다.

 

 

 

 

본 포스팅에서의 소스 설명은 소스 내부의 주석으로 대체한다.

 

기본적으로 파일 사이즈 비교 정도는 작성되어 있으나

 

실제로 사용할 경우에는 파일의 유무, 유형, 사이즈 등을 더 디테일하게 검사할 필요가 있다.

 



 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
<!DOCTYPE>
<HTML>
<BODY>
<script src="http://code.jquery.com/jquery-latest.js"></script>
 
<script type="text/javascript">
 
    // 파일 리스트 번호
    var fileIndex = 0;
    // 등록할 전체 파일 사이즈
    var totalFileSize = 0;
    // 파일 리스트
    var fileList = new Array();
    // 파일 사이즈 리스트
    var fileSizeList = new Array();
    // 등록 가능한 파일 사이즈 MB
    var uploadSize = 50;
    // 등록 가능한 총 파일 사이즈 MB
    var maxUploadSize = 500;
 
    $(function (){
        // 파일 드롭 다운
        fileDropDown();
    });
 
    // 파일 드롭 다운
    function fileDropDown(){
        var dropZone = $("#dropZone");
        //Drag기능 
        dropZone.on('dragenter',function(e){
            e.stopPropagation();
            e.preventDefault();
            // 드롭다운 영역 css
            dropZone.css('background-color','#E3F2FC');
        });
        dropZone.on('dragleave',function(e){
            e.stopPropagation();
            e.preventDefault();
            // 드롭다운 영역 css
            dropZone.css('background-color','#FFFFFF');
        });
        dropZone.on('dragover',function(e){
            e.stopPropagation();
            e.preventDefault();
            // 드롭다운 영역 css
            dropZone.css('background-color','#E3F2FC');
        });
        dropZone.on('drop',function(e){
            e.preventDefault();
            // 드롭다운 영역 css
            dropZone.css('background-color','#FFFFFF');
            
            var files = e.originalEvent.dataTransfer.files;
            if(files != null){
                if(files.length < 1){
                    alert("폴더 업로드 불가");
                    return;
                }
                selectFile(files)
            }else{
                alert("ERROR");
            }
        });
    }
 
    // 파일 선택시
    function selectFile(files){
        // 다중파일 등록
        if(files != null){
            for(var i = 0; i < files.length; i++){
                // 파일 이름
                var fileName = files[i].name;
                var fileNameArr = fileName.split("\.");
                // 확장자
                var ext = fileNameArr[fileNameArr.length - 1];
                // 파일 사이즈(단위 :MB)
                var fileSize = files[i].size / 1024 / 1024;
                
                if($.inArray(ext, ['exe''bat''sh''java''jsp''html''js''css''xml']) >= 0){
                    // 확장자 체크
                    alert("등록 불가 확장자");
                    break;
                }else if(fileSize > uploadSize){
                    // 파일 사이즈 체크
                    alert("용량 초과\n업로드 가능 용량 : " + uploadSize + " MB");
                    break;
                }else{
                    // 전체 파일 사이즈
                    totalFileSize += fileSize;
                    
                    // 파일 배열에 넣기
                    fileList[fileIndex] = files[i];
                    
                    // 파일 사이즈 배열에 넣기
                    fileSizeList[fileIndex] = fileSize;
 
                    // 업로드 파일 목록 생성
                    addFileList(fileIndex, fileName, fileSize);
 
                    // 파일 번호 증가
                    fileIndex++;
                }
            }
        }else{
            alert("ERROR");
        }
    }
 
    // 업로드 파일 목록 생성
    function addFileList(fIndex, fileName, fileSize){
        var html = "";
        html += "<tr id='fileTr_" + fIndex + "'>";
        html += "    <td class='left' >";
        html +=         fileName + " / " + fileSize + "MB "  + "<a href='#' onclick='deleteFile(" + fIndex + "); return false;' class='btn small bg_02'>삭제</a>"
        html += "    </td>"
        html += "</tr>"
 
        $('#fileTableTbody').append(html);
    }
 
    // 업로드 파일 삭제
    function deleteFile(fIndex){
        // 전체 파일 사이즈 수정
        totalFileSize -= fileSizeList[fIndex];
        
        // 파일 배열에서 삭제
        delete fileList[fIndex];
        
        // 파일 사이즈 배열 삭제
        delete fileSizeList[fIndex];
        
        // 업로드 파일 테이블 목록에서 삭제
        $("#fileTr_" + fIndex).remove();
    }
 
    // 파일 등록
    function uploadFile(){
        // 등록할 파일 리스트
        var uploadFileList = Object.keys(fileList);
 
        // 파일이 있는지 체크
        if(uploadFileList.length == 0){
            // 파일등록 경고창
            alert("파일이 없습니다.");
            return;
        }
        
        // 용량을 500MB를 넘을 경우 업로드 불가
        if(totalFileSize > maxUploadSize){
            // 파일 사이즈 초과 경고창
            alert("총 용량 초과\n총 업로드 가능 용량 : " + maxUploadSize + " MB");
            return;
        }
            
        if(confirm("등록 하시겠습니까?")){
            // 등록할 파일 리스트를 formData로 데이터 입력
            var form = $('#uploadForm');
            var formData = new FormData(form);
            for(var i = 0; i < uploadFileList.length; i++){
                formData.append('files', fileList[uploadFileList[i]]);
            }
            
            $.ajax({
                url:"업로드 경로",
                data:formData,
                type:'POST',
                enctype:'multipart/form-data',
                processData:false,
                contentType:false,
                dataType:'json',
                cache:false,
                success:function(result){
                    if(result.data.length > 0){
                        alert("성공");
                        location.reload();
                    }else{
                        alert("실패");
                        location.reload();
                    }
                }
            });
        }
    }
</script>
 
    <form name="uploadForm" id="uploadForm" enctype="multipart/form-data" method="post">
        <table class="table" width="100%" border="1px">
            <tbody id="fileTableTbody">
                <tr>
                    <td id="dropZone">
                        파일을 드래그 하세요
                    </td>
                </tr>
            </tbody>
        </table>
    </form>
        
    <a href="#" onclick="uploadFile(); return false;" class="btn bg_01">파일 업로드</a>
        
</BODY>
</HTML>
 
cs

 

 

 

 

  • 프로필사진
    2018.06.08 01:52

    비밀댓글입니다

    • 프로필사진
      Favicon of https://cofs.tistory.com BlogIcon 개발자 CofS2018.06.14 17:15 신고

      도움이 되셨다니 다행이네요
      질문주신 방법은 form 안에 너어두셔도 되고 아니면 파일을 추가했듯이 추가해 주시면 됩거라 생각되네요 ^^

  • 프로필사진
    2018.09.27 13:05

    비밀댓글입니다

    • 프로필사진
      2018.09.27 13:49

      비밀댓글입니다

    • 프로필사진
      박진호2018.09.27 15:40

      죄송한데 비밀댓글로 되어 있어 내용을 확인 못하고 있습니다 ㅠㅠ 다시한번 부탁드립니다 ㅠ

    • 프로필사진
      Favicon of https://cofs.tistory.com BlogIcon 개발자 CofS2018.09.27 15:47 신고

      안녕하세요 ㅎㅎ
      파일이 저장될 경로는 서버단에서 스트림이나 파일객체를 사용하여 지정해 주셔야 합니다
      해당 소스는 클라이언트단에서 파일을 업로드 하는 부분입니다

  • 프로필사진
    koa2018.10.17 10:37

    안녕하세요?
    공유해주신 소스 잘 활용해보려고 하는데 혹시 컨트롤러 부분은 참고할 내용이 있을지요?

    • 프로필사진
      Favicon of https://cofs.tistory.com BlogIcon 개발자 CofS2018.10.17 10:45 신고

      안녕하세요ㅎㅎ
      컨트롤러부분은 인터넷에 돌아다니는 파일 업로드 예제를 사용하시면 됩니다

  • 프로필사진
    sahwasa2019.03.21 16:31

    도움이 많이 됐습니다 감사합니다~

  • 프로필사진
    vuevelop2019.07.09 05:44

    감사의 인사 남기고 갑니다 :)
    아직 백엔드쪽은 구성하기 전인데 잘되었으면 좋겠네요 흑 ㅎㅎ

  • 프로필사진
    2019.07.17 15:24

    비밀댓글입니다

    • 프로필사진
      Favicon of https://cofs.tistory.com BlogIcon 개발자 CofS2019.07.17 16:34 신고

      안녕하세요 ~
      일단 해당 소스 그대로 사용했을땐 drop 이벤트가 두번 실행되지는 않네요 ;
      뭔가 소스 다른 부분에 문제가 있을것 같아요

      클릭으로 업로드 하시려면
      화면에 버튼 하나 놓으시고 input file 태그 숨김으로 생성하고 selectFile(files)함수와 같은 역할을 할 함수 만들어서 input file 태그에 onchange 이벤트로 selectFile() 함수 걸면 되요 ~
      감사합니다 ^^

    • 프로필사진
      2019.07.17 17:23

      비밀댓글입니다

    • 프로필사진
      Favicon of https://cofs.tistory.com BlogIcon 개발자 CofS2019.07.18 09:53 신고

      ㅎㅎ 넵 고생하세요

  • 프로필사진
    2019.09.27 00:06

    비밀댓글입니다

    • 프로필사진
      Favicon of https://cofs.tistory.com BlogIcon 개발자 CofS2019.09.27 10:07 신고

      전체과정을 다 쓰기엔 너무 길어서 요약해드려요ㅎㅎ
      파일을 전송하려면 file tag 또는 file object가 필요하고 db에 적제하려면 long object type으로 하셔야합니다ㅎㅎ
      도움이 되셨기를바래요

  • 프로필사진
    감사감사2019.11.06 17:38

    실제업로드 하기위해 "등록하시겠습니까?" 창뜬후 "확인"클릭했을때 submit 해서 upload.php(업로드처리페이지)로 넘겨서 처리 하고 싶은데 넘길수가 없네요. 몇일째 글쩍이는 중입니다. 혹시 등록된 파일을 input type=file 로 해서 upload.php(업로드처리페이지)로 어떻게 넘겨야 할까요?

    • 프로필사진
      Favicon of https://cofs.tistory.com BlogIcon 개발자 CofS2019.11.11 08:52 신고

      안녕하세요 ^^
      음... 파일 업로드를 할 때 파일 태그는 A페이지에 있고 실제 업로드는 B페이지에서 진행한다고 이해하면 될까요 ?
      그게 맞다면 B페이지에서 A페이지 태그를 참조해도 되고 혹은 A페이지에서 파일태그를 object로 변환 후 B페이지에서 참조해도 될 것 같습니다 ㅎㅎ