Back to the Spring

이미지 파일 다중 업로드, 미리보기 구현 ( AJAX )

Backcoder 2022. 9. 24. 21:59

게시글을 작성할 때, 단순하게 이미지 파일을 업로드 하는 방법은 정보도 많고, 구현이 간편하다.

 

1. <form method="post" enctype="multipart/form-data"> 

2. <input type="file" ~ > 

3. Controller => MultipartFile file 로 받아주기 

 

여러 이미지를 올리고 싶으면

A. <input type="file" ~> 을 여러개 만들거나 

B. <input type="file" multiple="multiple" >  멀티플 속성을 달아주면 된다.

 

- 근데, 이렇게 하면 

 

A의 경우 => 파일첨부 칸이 여러줄 생겨서 UI 매력이 떨어진다 

B의 경우 => 사용자들이 shift 로 여러파일을 선택하기 불편하다 ( 모르는 분들도 많다 ) 

 

 

또한, 저대로만 만들어두게 되면 

사용자가 업로드한 이미지 파일을 글 작성 페이지에서 눈으로 보면서 작성할 수 없다.

 

 

마침, 이런 생각을 가지고 

이미지를 Preview 로 띄워주는 코딩을 구현해보고 있는데 

(지긋지긋한) 예비군에서 반가운 연락이 오랜만에 와서

연기하려고 예비군 사이트에 들어가서 이미지 파일을 첨부하려 했더니 

B의 경우와 유사하게 되어있어, 내가 올린 이미지파일을 해당 페이지에서 볼 수 없었다. 

무슨 수를 써서라도 프리뷰는 구현해봐야겠다 는 동기부여가 됬다. 

 

 

=>  AJAX 를 사용하는 방향을 택했다.

 

 

[ Body ] 

<form  id="uploadForm" action="http://localhost:8090/registerProduct" method="post" enctype="multipart/form-data">

<table>

~

</table>
<br>


물품사진 : <input id="imgFile" type="file" name="imgFile"><br>
<input id="file1" type="text" style="display:none" name="file1">
<input id="file2" type="text" style="display:none" name="file2">
<br>
<input type="submit" value="물품등록">
</form>

 

 

=> 사용자에게는 파일첨부하는 한 줄만 노출되고, 

파일 선택을 하게되면,  script 에서 AJAX 로 파일을 보내고

응답을 받아 실시간으로 해당 사진을 페이지에 띄운다.   

( 동시에, 해당 파일의 이름들은 input text 로 안보이게 넣어둔다. ) 

 

 

[ 스크립트 ] 

 

<script>
$(document).ready(function(){
  
$("#imgFile").change(function(e) {
e.preventDefault();

var form = $("#uploadForm")[0];
var data = new FormData(form);

$.ajax({
url : "ajaxUpload",
data : data,
type : "post",
dataType : "json",

encType : "multipart/form-data",
processData : false,  
contentType : false,  

success : function(resp){ 

$("#here").append("<img src='http://localhost:8090/upload/"+resp.result+"' height=200 width=200 >");
 
  switch ("") {
  case $("#file1").val():
   $("#file1").val(resp.result);
      break;
    case $("#file2").val():
   $("#file2").val(resp.result);
      break;
  }

} // success 
}); // ajax 
}); // onclick
}); // onload 
</script>

 

 

[ 컨트롤러 ] 

@ResponseBody
@PostMapping(value ="/ajaxUpload", produces= {"application/json; charset=utf-8"})
public String uploadajax(MultipartFile imgFile) throws IOException {

String savePath = "c:/upload/";

String originalname1 = imgFile.getOriginalFilename();
String onlyfilename = originalname1.substring(0, originalname1.indexOf("."));
String extname = originalname1.substring(originalname1.indexOf("."));
String newname = onlyfilename + "(" + UUID.randomUUID().toString()+")" + extname;
File serverfile1 = new File(savePath + newname);
imgFile.transferTo(serverfile1);

return "{\"result\" : \"" + newname + "\" }";
}

 

 

=> AJAX 로 받아서, 서버에 업로드 시킨 뒤 해당 파일명(UUID)을 RESTAPI 로 응답해준다. 

파일명이 들어올 때 마다, input text 에 받아서 집어넣어 둔다. 

( 파일명은 UploadDTO 를 만들어서 String 으로 받는다. ) 

 

 

@PostMapping("/registerProduct")
public String registerProcess(ProductDTO dto, UploadDTO uploaddto) throws Exception{

// 이미지 Set 
if(uploaddto.getFile1()!=null) {
dto.setImg1(uploaddto.getFile1());
}
if(uploaddto.getFile2()!=null) {
dto.setImg2(uploaddto.getFile2());
}


productDAO.insertBoard(dto);
return "redirect:/allproduct";
}

 

 

[ 전체적 흐름 ] 

1. 파일 첨부 시, AJAX 로 해당 파일을 업로드, 파일명을 Rest API 로 응답 

2. 응답을 받아 해당 이미지 파일을 미리보기로 제공, 해당파일 명 String 에 저장해둠 

3. Submit 하게 되면 String 이름들과 DTO 정보 넘어오고, DB 저장 => 필요시 가져다 사용 

 

 

 

[ 수정 시 ] 

1. DB 에서 파일이름으로 가져와서 View 로 뿌려줌과 동시에,

<input type="file> 의 value 값에 넣어 둔다. 

2. 이후에 사용자가 업로드하는 파일들은 value 값이 없는  <input type="file" > 에 순서대로 들어가게 된다.  

 

 

===

 

 

 

 

생각보다 이미지 업로드 시, 미리보기 구현등에 관한 정보가 많지 않았다.

결국 AJAX 로 혼자 깔짝대보다가  

혼자 힘으로 구현해 내고나니 일단은 뿌듯함이 앞선다. 

( 리팩토링 해야할 게 많지만... )

 

어떻게 구현할지 계속 생각하고, 시도해보고,

오류랑 싸우고 부대끼면서 프로그래밍을 해나가는 과정속에서 많이 성장하게 되는 것 같다.