- 첨부파일 자체의 처리는 Ajax를 통해 이루어지므로, 게시물의 등록 시점에는 현재 서버에 업로드된 파일들에 정보를 등록하려는 게시물의 정보와 같이 전송해서 처리한다.
- 이 작업은 게시물의 등록 버튼을 클릭했을 때 현재 서버에 업로드된 파일의 정보를 < input type='hidden' > 으로 만들어서 한 번에 전송하는 방식을 사용한다.
- 게시물의 등록을 담당하는 /board/register.jsp 파일에서 첨부파일을 추가할 수 있도록 수정하는 작업부터 시작한다.
- 기존 게시물의 제목이나 내용을 입력하는 부분 아래쪽에 새로운 < div > 를 추가한다.
< register.jsp > <div class="row"> <div class="col-lg-12"> <div class="panel panel-default"> <div class="panel-heading">File Attach</div> <!-- /.panel-heading --> <div class="panel-body"> <div dlass="form-group uploadDiv"> <input type='file' name='uploadFile' multiple> </div> <div class='uploadResult'> <ul> </ul> </div> <!-- end panel-body --> </div> <!-- end panel-body --> </div> <!-- end panel --> </div> <!-- /.row -->
- 추가된 < div > 안에는 이전 예제에서 사용한 < div class='uploadResult' > 등을 추가해 파일 업로드한 결과를 처리할 수 있도록 한다.
- 브라우저에서는 새로운 부분이 아래와 같이 추가되는 것을 확인할 수 있다.
- 업로드를 위한 uploadAjax.jsp의 CSS 부분도 register.jsp 내에 추가한다.
- 복잡한 부분은 파일을 선택하거나 'Submit Button'을 클릭했을 때의 JavaScript 처리다.
< register.jsp > <script> $(document).ready(function(e){ var formObj = $("form[role='form']"); $("button[type='submit']").on("click", function(e){ e.preventDefault(); console.log("submit clicked"); }); }); </script>
- 파일의 업로드는 별도의 업로드 버튼을 두지 않고, < input type='file' > 의 내용이 변경되는 것을 감지해서 처리하도록 한다.
- $(document).ready() 내에 파일 업로드 시 필요한 코드를 아래와 같이 추가한다.
< register.jsp > var regex = new RegExp("(.*?)\.(exe|sh|zip|alz)$"); var maxSize = 5242880; //5MB function checkExtension(fileName, fileSize){ if(fileSize >= maxSize){ alert("파일 사이즈 초과"); return false; } if(regex.test(fileName)){ alert("해당 종류의 파일은 업로드 할 수 없습니다."); return false; } return true; } $("input[type='file']").change(function(e){ var formData = new FormData(); var inputFile = $("input[name='uploadFile']"); var files = inputFile[0].files; for(var i = 0; i < files.length; i++) { if(!checkExtension(files[i].name, files[i].size) ) { return false; } formData.append("uploadFile", files[i]); } $.ajax({ url: '/uploadAjaxAction', processData: false, contentType: false,data: formData,type: 'POST', dataType: 'json', success: function(result){ console.log(result); //showUploadResult(result); // 업로드 결과 처리 함수 } }); //$.ajax });
- 첨부된 파일의 처리는 기존과 동일하지만 아직은 섬네일이나 파일 아이콘을 보여주는 부분은 처리하지 않는다.
- 브라우저의 콘솔창을 이용해 업로드가 정상적으로 처리되는지 만을 확인한다.
- 아래 화면은 첨부파일을 3개 추가하는 경우 업로드 결과를 콘솔창에서 확인한 모습이다.
- 업로드된 결과를 화면에 섬네일 등을 만들어서 처리하는 부분은 별도의 showUploadResult() 함수를 제작하고 결과를 반영한다.
< register.jsp > function showUploadResult(uploadResultArr){ if(!uploadResultArr || uploadResultArr.length == 0){ return; } var uploadUL = $(".uploadResult ul"); var str =""; $(uploadResultArr).each(function(i, obj){ //image type if(obj.image){ ... }else{ ... } }); uploadUL.append(str); }
- showUploadResult()는 Ajax 호출 후에 업로드된 결괄르 처리하는 함수이므로, 이전의 코드에서 $.ajax() 호출 부분의 주석 처리한 부분을 해제한다.
$.ajax({ url: '/uploadAjaxAction', processData: false, contentType: false,data: formData,type: 'POST', dataType: 'json', success: function(result){ console.log(result); showUploadResult(result); // 업로드 결과 처리 함수 } }); //$.ajax
- 이미지 파일인 경우와 일반 파일의 경우에 보여지는 화면의 내용은 shwoUploadResult()내에 아래와 같은 HTML 태그들을 이용해 작성한다.
//image type if(obj.image){ var fileCallPath = encodeURIComponent( obj.uploadPath+ "/s_"+obj.uuid +"_"+obj.fileName); str += "<li><div>"; str += "<span> "+ obj.fileName+"</span>"; str += "<button type='button' class='btn btn-warning btn-circle'><i class='fa fa-times'></i></button><br>"; str += "<img src='/display?fileName="+fileCallPath+"'>"; str += "</div>"; str +"</li>"; }else{ var fileCallPath = encodeURIComponent( obj.uploadPath+"/"+ obj.uuid +"_"+obj.fileName); var fileLink = fileCallPath.replace(new RegExp(/\\/g),"/"); str += "<li><div>"; str += "<span> "+ obj.fileName+"</span>"; str += "<button type='button' class='btn btn-warning btn-circle'><i class='fa fa-times'></i></button><br>"; str += "<img src='/resources/img/attach.png'></a>"; str += "</div>"; str +"</li>"; }
- 게시물 등록 화면에서 첨부파일이 업로드되면 아래와 같은 모습으로 보이게 된다.
- 첨부팡리의 변경은 사실상 업로드된 파일의 삭제이므로 'x' 모양의 아이콘을 클릭할 때 이루어지도록 이벤트를 처리한다.
$(".uploadResult").on("click", "button", function(e){ console.log("delete file"); });
- 업로드된 파일에 'x' 아이콘을 클릭하면 콘솔창에 'delete file'이 출력되는 것을 볼 수 있다.
- 삭제를 위해서는 업로드된 파일의 경로와 UUID가 포함된 파일 이름이 필요하므로 앞서 작성된 부분을 수정한다.
- < button > 태그에 'data-file'과 'data-type' 정보를 추가한다.
//image type if(obj.image){ var fileCallPath = encodeURIComponent( obj.uploadPath+ "/s_"+obj.uuid +"_"+obj.fileName); str += "<li><div>"; str += "<span> "+ obj.fileName+"</span>"; str += "<button type='button' data-file=\'"+fileCallPath+"\' data-type='image' class='btn btn-warning btn-circle'><i class='fa fa-times'></i></button><br>"; str += "<img src='/display?fileName="+fileCallPath+"'>"; str += "</div>"; str +"</li>"; }else{ var fileCallPath = encodeURIComponent( obj.uploadPath+"/"+ obj.uuid +"_"+obj.fileName); var fileLink = fileCallPath.replace(new RegExp(/\\/g),"/"); str += "<li><div>"; str += "<span> "+ obj.fileName+"</span>"; str += "<button type='button' data-file=\'"+fileCallPath+"\' data-type='file' class='btn btn-warning btn-circle'><i class='fa fa-times'></i></button><br>"; str += "<img src='/resources/img/attach.png'></a>"; str += "</div>"; str +"</li>"; }
- 'x' 아이콘을 클릭하면 서버에서 삭제하도록 이벤트를 처리한다.
$(".uploadResult").on("click", "button", function(e){ console.log("delete file"); var targetFile = $(this).data("file"); var type = $(this).data("type"); var targetLi = $(this).closest("li"); $.ajax({ url: '/deleteFile', data: {fileName: targetFile, type:type}, dataType: 'text', type: 'POST', success: function(result){ alert(result); targetLi.remove(); } }); //$.ajax });
- 브라우저에서 첨부파일을 삭제하면 업로드된 파일도 같이 삭제되는 것을 확인할 수 있다.
- 게시물의 등록 과정에서는 첨부파일의 상세 조희는 의미가 없고, 단순히 새로운 첨부파일을 추가하거나 삭제해서 자신이 원하는 파일을 게시물 등록할 때 같이 포함하도록 한다.
- Ajax를 이용하는 경우 이미 어떠한 파일을 첨부로 처리할 것인지는 이미 완료된 상태이므로 남은 작업은 게시물이 등록될 때 첨부파일과 관련된 자료를 같이 전송하고, 이를 데이터베이스에 등록하는 것이다.
- 게시물의 등록은 < form > 태그를 통해 이루어지므로 이미 업로드된 첨부파일의 정보는 별도의 < input type='hidden' > 태그를 생성해 처리한다.
- 이를 위해서는 첨부파일 정보를 태그로 생성할 때 첨부파일과 관련된 정보(data-uuid, data-filename, data-type)를 추가한다.
if(obj.image){ var fileCallPath = encodeURIComponent( obj.uploadPath+ "/s_"+obj.uuid +"_"+obj.fileName); str += "<li data-path='"+obj.uploadPath+"'"; str +=" data-uuid='"+obj.uuid+"' data-filename='"+obj.fileName+"' data-type='"+obj.image+"'" str +" ><div>"; str += "<span> "+ obj.fileName+"</span>"; str += "<button type='button' data-file=\'"+fileCallPath+"\' " str += "data-type='image' class='btn btn-warning btn-circle'><i class='fa fa-times'></i></button><br>"; str += "<img src='/display?fileName="+fileCallPath+"'>"; str += "</div>"; str +"</li>"; }else{ var fileCallPath = encodeURIComponent( obj.uploadPath+"/"+ obj.uuid +"_"+obj.fileName); var fileLink = fileCallPath.replace(new RegExp(/\\/g),"/"); str += "<li " str += "data-path='"+obj.uploadPath+"' data-uuid='"+obj.uuid+"' data-filename='"+obj.fileName+"' data-type='"+obj.image+"' ><div>"; str += "<span> "+ obj.fileName+"</span>"; str += "<button type='button' data-file=\'"+fileCallPath+"\' data-type='file' " str += "class='btn btn-warning btn-circle'><i class='fa fa-times'></i></button><br>"; str += "<img src='/resources/img/attach.png'></a>"; str += "</div>"; str +"</li>"; }
업로드된 정보는 JSON으로 처리
JSON정보는 < input type='hidden' >으로 변환
- < input type='hidden' > 으로 처리된 첨부파일의 정보는 BoardVO로 수집된다.
- BoardVO에는 attachList라는 이름의 변수로 첨부파일의 정보를 수집하기 때문에 < input type='hidden' > 의 name은 'attachList[인덱스번호]'와 같은 이름을 사용하도록 한다.
- JSP 화면에서는 JavaScript를 이용해 기존에 < form > 태그를 전송하는 부분을 아래와 같이 수정한다.
< register.jsp > var formObj = $("form[role='form']"); $("button[type='submit']").on("click", function(e){ e.preventDefault(); console.log("submit clicked"); var str = ""; $(".uploadResult ul li").each(function(i, obj){ var jobj = $(obj); console.dir(jobj); str += "<input type='hidden' name='attachList["+i+"].fileName' value='"+jobj.data("filename")+"'>"; str += "<input type='hidden' name='attachList["+i+"].uuid' value='"+jobj.data("uuid")+"'>"; str += "<input type='hidden' name='attachList["+i+"].uploadPath' value='"+jobj.data("path")+"'>"; str += "<input type='hidden' name='attachList["+i+"].fileType' value='"+ jobj.data("type")+"'>"; }); formObj.append(str).submit(); });
- 브라우저에서 게시물 등록을 선택하면 이미 업로드된 항목들을 내부적으로 < input type='hidden' > 태그들로 만들어서 < form > 태그가 submit 될 때 같이 전송되도록 한다.