Chapter 24-3

ChangWoo·2023년 11월 20일
0
post-thumbnail

Part 24. 첨부파일의 다운로드 혹은 원본 보여주기

24.3 첨부파일 삭제

  • 첨부파일 삭제는 생각보다 많은 고민이 필요한 작업이다.
  • 단순히 파일 하나만을 삭제한다고 생각할 수 있지만 실제로는 다음과 같은 문제점들을 고민해야 한다.
    • 이미지 파일의 경우에는 섬네일까지 같이 삭제되어야 하는 점
    • 파일을 삭제한 후에는 브라우저에서도 섬네일이나 파일 아이콘이 삭제되도록 처리하는 점
    • 비정상적으로 브라우저의 종료 시 업로드된 파일의 처리

24.3.1 일반 파일과 이미지 파일의 삭제

  • 업로드된 첨부파일의 삭제는 Ajax를 이용하거나 < form > 태그를 이용하는 방식 모두를 적용할 수 있다.
  • 이미 업로드된 첨부파일의 삭제는 일반 파일의 경우에는 업로드된 파일만을 삭제하면 되지만, 이미지의 경우에는 생성된 섬네일 파일과 원본 파일을 같이 삭제해야 한다.
  • 서버 측에서는 삭제하려는 파일의 확장자를 검사해서 일반 파일인지 이미지 파일인지를 파악하거나 파라미터로 파일의 종류를 파악하고, 이를 이용해 처리를 다르게 한다.

화면에서 삭제 기능

  • 첨부파일이 업로드된 후에 생기는 이미지 파일 옆에 'x' 표시를 추가하도록 아래와 같이 수정한다.
< uploadAjax.jsp >
function showUploadedFile(uploadResultArr){
			   var str = "";
			   $(uploadResultArr).each(function(i, obj){
			     if(!obj.image){
			       var fileCallPath =  encodeURIComponent( obj.uploadPath+"/"+ obj.uuid +"_"+obj.fileName);
			       var fileLink = fileCallPath.replace(new RegExp(/\\/g),"/");
			       str += "<li><a href='/download?fileName="+fileCallPath+"'><img src='/resources/img/attach.png'>"+obj.fileName+"</a>"+
			    	   "<span data-file=\'"+fileCallPath+"\' data-type='file'> x </span>"+ 
			    	   "<div></li>"
			     }else{
			       var fileCallPath =  encodeURIComponent( obj.uploadPath+ "/s_"+obj.uuid +"_"+obj.fileName);
			       var originPath = obj.uploadPath+ "\\"+obj.uuid +"_"+obj.fileName;
			       originPath = originPath.replace(new RegExp(/\\/g),"/");
			       str += "<li><a href=\"javascript:showImage(\'"+originPath+"\')\"><img src='/display?fileName="+fileCallPath+"'></a>"+
			    	   "<span data-file=\'"+fileCallPath+"\' data-type='image'> x </span>"+
			    	   "<li>";
			     }
			   });
			   uploadResult.append(str);
			 } 
  • 변경된 부분은 < span > 태그를 이용해 섬네일이나 파일 아이콘 옆에 'x' 표시를 추가한 점과 < span > 태그에 'data-file'과 'data-type' 속성을 추가한 부분이다.
  • 화면을 보면 테스트할 수 있도록 만든 'x'표시가 보인다.
  • 'x'표시에 대한 이벤트 처리는 아래와 같이 작성한다.
< uploadAjax.jsp >
		$(".uploadResult").on("click","span", function(e){
			  var targetFile = $(this).data("file");
			  var type = $(this).data("type");
			  console.log(targetFile);
			  $.ajax({
			    url: '/deleteFile',
			    data: {fileName: targetFile, type:type},
			    dataType:'text',
			    type: 'POST',
			      success: function(result){
			         alert(result);
			       }
			  }); //$.ajax
			});
  • 첨부파일의 삭제는 < span > 태그를 이용해 처리하지만, 첨부파일의 업로드 후에 생성되기 때문에 '이벤트 위임' 방식으로 처리해야 한다.
  • 이벤트 처리에서는 Ajax를 이용해서 첨부파일의 경로와 이름, 파일의 종류(이미지 혹은 일반)를 전송한다.

서버에서 첨부파일의 삭제

  • 서버 측에서 첨부파일은 전달되는 파라미터의 이름과 종류를 파악해 처리한다.
< UploadController >
@PostMapping("/deleteFile")
	@ResponseBody
	public ResponseEntity<String> deleteFile(String fileName, String type) {
		log.info("deleteFile: " + fileName);
		File file;
		try {
			file = new File("d:\\upload\\" + URLDecoder.decode(fileName,"UTF-8"));
			file.delete();
			if (type.equals("image")) {
				String largeFileName = file.getAbsolutePath().replace("s_", "");
				log.info("largeFileName: " + largeFileName);
				file = new File(largeFileName);
				file.delete();
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return new ResponseEntity<>(HttpStatus.NOT_FOUND);
		}
		return new ResponseEntity<String>("deleted", HttpStatus.OK);
	}
  • deleteFIle()은 브라우저에서 전송하는 파일 이름과 종류를 파라미터로 받아서 파일의 종류에 따라 다르게 동작한다.
  • 브라우저에서 전송되는 파일 이름은 '경로+UUID+_+파일이름'으로 구성되어 있으므로, 일반 파일의 경우에는 파일만을 삭제한다.
  • 이미지의 경우 섬네일이 존재하므로, 파일 이름의 중간에 's_'가 들어가 있다.
  • 일반 이미지 파일의 경우 's_'가 없도록 되어 있으므로, 이 부분을 변경해 원본 이미지 파일도 같이 삭제하도록 처리한다.

24.3.2 첨부파일의 삭제 고민

  • 첨부파일을 삭제하는 작업의 최대 고민은 사용자가 비정상적으로 브라우저를 종료하고 나가는 행위다.
  • 서버에는 Ajax를 이용해 업로드했기 때문에 이미 저장이 된 상태지만, 사용자가 '작업 관리자'나 전원 버튼을 누르는 등의 조치를 해서 브라우저 자체를 종료해 버린다면 이를 감지할 수 있는 적당한 방법이 없다(브라우저의 창이 닫히는 이벤트는 가능하지만 비정상적인 종료는 문제가 된다.).
  • 이에 대한 가장 좋은 해결책은 실제 최종적인 결과와 서버에 업로드된 파일의 목록을 비교해서 처리하는 것이다.
  • 보통 이런 작업은 spring-batch나 Quartz 라이브러리를 이용해 처리한다.
profile
한 걸음 한 걸음 나아가는 개발자

0개의 댓글