10/09/2018

스프링 쇼핑몰 만들기 #12. 상품 수정간 이미지 변경 기능 구현

스프링 쇼핑몰 만들기
 - 깃허브 링크

상품 등록시 이미지 첨부 기능이 구현되었는데, 상품을 수정할 때 이미지를 수정하는 기능은 아직 없습니다.

상품을 수정할 때 이미지를 변경 안하는 경우도 있고, 변경하는 경우도 있습니다. 이미지를 변경하지 않았을 땐 기존에 있는 이미지를 다시 데이터 베이스에 저장하거나, 이미지를 다루지 않는 쿼리문을 이용하면 되는데, 저는 기존에 있는 이미지를 다시 데이터 베이스에 저장하는 방법으로 하겠습니다.

register.jsp에 있는 이미지 관련 코드를 복사해서 modify.jsp로 붙여넣습니다. 그리고 기존 이미지를 출력하는 HTML코드와 원본 이미지와 썸네일을 저장하는 숨겨진(hidden) 인풋박스를 추가했습니다.

<div class="inputArea">
<label for="gdsImg">이미지</label>
<input type="file" id="gdsImg" name="file" />
<div class="select_img">
<img src="${goods.gdsImg}" />
<input type="hidden" name="gdsImg" value="${goods.gdsImg}" />
<input type="hidden" name="gdsThumbImg" value="${goods.gdsThumbImg}" />
</div>

<script>
$("#gdsImg").change(function(){
if(this.files && this.files[0]) {
var reader = new FileReader;
reader.onload = function(data) {
$(".select_img img").attr("src", data.target.result).width(500);
}
reader.readAsDataURL(this.files[0]);
}
});
</script>
<%=request.getRealPath("/") %>
</div>

또, modify.jsp의 폼(form)에 파일 관련된 속성을 부여합니다.

enctype="multipart/form-data"

이미지가 원본 크기 그대로 나오면 너무 클테니, 스타일(CSS)에 적당한 크기를 설정해줍니다.

매퍼의 쿼리에 이미지와 썸네일을 추가합니다.

<!-- 상품 수정 -->
<update id="goodsModify">
update tbl_goods
    set
        gdsName = #{gdsName},
        cateCode = #{cateCode},
        gdsPrice = #{gdsPrice},
        gdsStock = #{gdsStock},
        gdsDes = #{gdsDes},
       
        gdsImg = #{gdsImg},
        gdsThumbImg = #{gdsThumbImg}
       
    where gdsNum = ${gdsNum}
</update>

컨트롤러 상품 수정 메서드의 매개변수와 내부 코드를 추가합니다.

// 상품 수정
@RequestMapping(value = "/goods/modify", method = RequestMethod.POST)
public String postGoodsModify(GoodsVO vo, MultipartFile file, HttpServletRequest req) throws Exception {
logger.info("post goods modify");

// 새로운 파일이 등록되었는지 확인
if(file.getOriginalFilename() != null && file.getOriginalFilename() != "") {
// 기존 파일을 삭제
new File(uploadPath + req.getParameter("gdsImg")).delete();
new File(uploadPath + req.getParameter("gdsThumbImg")).delete();

// 새로 첨부한 파일을 등록
String imgUploadPath = uploadPath + File.separator + "imgUpload";
String ymdPath = UploadFileUtils.calcPath(imgUploadPath);
String fileName = UploadFileUtils.fileUpload(imgUploadPath, file.getOriginalFilename(), file.getBytes(), ymdPath);

vo.setGdsImg(File.separator + "imgUpload" + ymdPath + File.separator + fileName);
vo.setGdsThumbImg(File.separator + "imgUpload" + ymdPath + File.separator + "s" + File.separator + "s_" + fileName);

} else {  // 새로운 파일이 등록되지 않았다면
// 기존 이미지를 그대로 사용
vo.setGdsImg(req.getParameter("gdsImg"));
vo.setGdsThumbImg(req.getParameter("gdsThumbImg"));

}

adminService.goodsModify(vo);

return "redirect:/admin/index";
}

상품 등록 메서드와 거의 같은 코드인데, 새로운 이미지 파일이 등록되었는지 확인하는 과정이 추가되었습니다.

새로운 이미지가 등록되지 않았다면 기존 이미지를 그대로 사용하고, 새로운 이미지가 등록되었다면 기존 이미지를 삭제한 뒤 새로운 이미지를 등록합니다.

이제 상품 수정을 해봅니다. 일단 기존에 저장했던 이미지는 정상적으로 잘 나오네요.

이미지를 교체했습니다.

완료 버튼을 클릭하면 기존에 사용하던 이미지 파일은 삭제되고 새로운 이미지 파일이 등록되어야합니다.

상품 조회를 해보니 새로운 이미지가 잘 나옵니다.

기존에 등록했던 이미지 파일은 아예 삭제 되었습니다.

그리고 새로운 이미지 파일은 저장이 되어있습니다.

이번엔 이미지를 변경하지 않고 다른 내용만 변경해보겠습니다.

이미지는 그대로 유지되었으며 내용도 잘 변경되었습니다.

게시물 수정
  1. 컨트롤러부분에서 getOriginalFilename() != null && getOriginalFilename() !="" 이부분에서 파일 수정하지 않고
    수정 눌러도 저 if문에서 계속 조건에 만족하게되네요 ㅠ

    답글삭제
    답글
    1. 아 해결했습니다 ㅠ file.getOriginalFilename()!= null && !file.getOriginalFilename().equals("")로 하니까 되네여

      삭제
    2. 근데 의문점 하나가 이미지 수정없이 수정 누르면 !file.getOriginalFilename().equals("")이걸로 하면 log로 찍어보니까 false가 나오고 file.getOriginalFilename() !=null로 하면 트루가 나옵니다.

      삭제
    3. 안녕하세요?

      jsp에서 컨트롤러로 넘어오는 과정에서 파일 인풋박스에 있는 value=""가 그대로 넘어오기 때문에 그런것 같습니다. 없는 문자("")라고 했지만 일단 존재하다보니(?) !file.getOriginalFilename().equals("")에서 !true가 되어 로그에 false가 출력되고, file.getOriginalFilename() != null에서는단 NULL이 아니라 ""이기 때문에 true가 출력되는것 같네요.

      중요한건 조건문의 결과보다 jsp에서 컨트롤러로 넘어온 데이터인것 같습니다.

      그나저나 저는 왜 equals를 안썼을까요-_-; 죄송합니다;

      삭제
  2. 익명5/18/2021

    안녕하세요! kuzuro님 ! 요즘 spring 쇼핑몰 비슷한 프로젝트 개발 중인데 너무 잘 보고 있고 감사드립니다. 이미지 업로드를 할 때, resource/image 폴더 안에 저장을 했는데, 불러올때 빠르면 3~5초, 느리면 20초까지 불러오는 시간이 걸리더라구요..ㅠ 그래서 이미지를 img src="경로" 바로 받아오지 못해 그 시간동안 이미지가 나오지 않습니다. 이럴때는 어떻게 해야 할까요? aws 같은 서버에 올리면 해결된다는 이야기가 있는데(현재는 로컬, 노트북 환경에서 개발 중입니다. 상대적으로 느리긴 한...) 맞을까요.. ? 혹시 이런 딜레이 문제 겪어보신 적 있으신가요?

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      로컬에서 불러오는 이미지가 늦는 경우는 본적이 없는데.. 실제로 이미지 때문에 출력이 늦는건지 확인해보셔야할것 같습니다.

      삭제
  3. 안녕하세요. 덕분에 정말 잘 배우고 있습니다. 다름이 아니라 메퍼에서 gdsImg = #{gdsImg}, gdsThumbImg = #{gdsThumbImg}를 인식하지 못하고 있는 것 같습니다. 조언 부탁드립니다 ㅠㅠ 감사합니다

    INFO : jdbc.audit - 22. Connection.prepareStatement(update tbl_goods
    set
    gdsName = ?,
    cateCode = ?,
    gdsPrice = ?,
    gdsStock = ?,
    gdsDes = ?
    where gdsNum = 2) returned net.sf.log4jdbc.sql.jdbcapi.PreparedStatementSpy@6233bc1

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      말씀하신 문제와 올리신 코드는 별개입니다.
      올리신 코드는 ?에 들어가는 데이터의 타입이 맞지 않거나 null일때 발생하는 에러입니다.

      삭제
  4. 해봤는데 사진삭제가 안되고 그대로 남아있는상태에서 새로운 사진만 추가되는데요 ㅠ 무슨문제일까요

    답글삭제
    답글
    1. 해봤는데 사진삭제가 안되고 그대로 남아있는상태에서 새로운 사진만 추가되는데요 ㅠ 무슨문제일까요
      그리고 디비에 저장되는 이름이 바뀌어요
      \imgUpload\2021\11\25\2bdc6748-5d55-4a09-a7f5-f6a5e1771043_아이번.jpg 이런 이름에서
      /ex06/resources/\imgUpload\2021\11\25\0c2df209-f289-4623-b3f4-c3c3a80fc09b_맥주.jpg 이렇게 바뀝니다
      그리고 이미지 안바꾸고 글만수정하면 깨진이미지로 나옵니다 ㅠ

      삭제
    2. 앗해결햇습니다

      삭제
  5. 안녕하세요. 항상 감사합니다 ^^
    제가 해당 예제를 따라하다가 수정하기 버튼을 눌렀는데 db에도 변화가 없고
    제 원래 게시판이 게시글에 이미지를 띄우는 게시판인데 이미지도 깨진 아이콘이 뜨더라구요!
    혹시 위의 문제라면 어느 부분이 잘못된 것일까요? 아직 초보라 ㅠㅠ

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      기간이 좀..아니, 꽤 지난 댓글인데..;

      게시판 수정하기를 했을때 이미지가 안나올 경우라면
      아마 수정하는 과정에서 이미지를 추가하지 않은 경우(즉, 이미지쪽은 아예 손대지 않은 경우) null값이 전달되어서 해당 이미지가 깨지는것으로 예상됩니다.

      이런 경우 이미지가 바뀌었는지(재업로드 포함) 확인하고, 안바뀌었다면 이미지 부분 로직은 그냥 넘겨버리는 방식으로 처리하셔도 되겠습니다.

      삭제
  6. 잘 보고 갑니다 감사합니다

    답글삭제