[Spring] 게시글의 이미지 수정하기

layl__a·2022년 9월 21일
0

Spring Boot

목록 보기
11/17

이미지 수정폼 만들기

ArticleController.java

@PreAuthorize("isAuthenticated()")
@GetMapping("/{id}/modify")
public String showModify(@AuthenticationPrincipal MemberContext memberContext, Model model, @PathVariable Long id) {
    Article article = articleService.getForPrintArticleById(id);

    if (memberContext.memberIsNot(article.getAuthor())) {
        throw new ResponseStatusException(HttpStatus.FORBIDDEN);
    }

    model.addAttribute("article", article);

    return "article/modify";
}

@PostMapping("/{id}/modify")
public String modify(@AuthenticationPrincipal MemberContext memberContext, Model model, @PathVariable Long id, @Valid ArticleForm articleForm) {
    return "/article/%d".formatted(id);
}
  • 수정페이지를 들어가기 위해서는 article을 수정하려는 Author와 member의 정보가 일치하는지 확인해야 하기 때문에 memberContextmemberIsNot 메서드를 사용했다.

MemberContext.java

public boolean memberIs(Member member) {
        return id.equals(member.getId());
    }

    public boolean memberIsNot(Member member) {
        return memberIs(member) == false;
    }

modify.html

<!DOCTYPE html>
<html layout:decorate="~{layout/layout.html}">

<head>
    <title>글수정</title>
</head>

<body>
<section layout:fragment="content">
    <div class="container">
        <h1>글수정</h1>

        <script>
            function ModifyForm__submit(form) {
                form.subject.value = form.subject.value.trim();

                if (form.subject.value.length == 0) {
                    alert("제목을 입력해주세요.");
                    form.subject.focus();
                    return;
                }

                form.content.value = form.content.value.trim();

                if (form.content.value.length == 0) {
                    alert("내용을 입력해주세요.");
                    form.content.focus();
                    return;
                }

                form.submit();
            }

        </script>

        <form th:action method="POST" enctype="multipart/form-data" onsubmit="ModifyForm__submit(this); return false;">
            <div>
                <span>제목</span>
                <input type="text" name="subject" th:value="${article.subject}">
            </div>
            <div>
                <span>내용</span>
                <textarea name="content" th:text="${article.content}"></textarea>
            </div>
            <div>
                <span>본문이미지</span>
                <div>
                    <input type="file" name="common__inBody__1" accept="image/png, image/gif, image/jpeg">
                </div>
                <div>
                    <input type="file" name="common__inBody__2" accept="image/png, image/gif, image/jpeg">
                </div>
            </div>
            <div>
                <span>글수정</span>
                <input type="submit" value="">
            </div>
        </form>
    </div>
</section>
</body>
</html>
  • write.html 과 같은 구조를 가지고 있다.

게시글 수정 api 만들기

ArticleController

@PreAuthorize("isAuthenticated()")
@PostMapping("/{id}/modify")
public String modify(@AuthenticationPrincipal MemberContext memberContext, Model model, @PathVariable Long id, @Valid ArticleForm articleForm) {
    Article article = articleService.getForPrintArticleById(id);

    if (memberContext.memberIsNot(article.getAuthor())) {
        throw new ResponseStatusException(HttpStatus.FORBIDDEN);
    }

    articleService.modify(article, articleForm.getSubject(), articleForm.getContent());

    String msg = Util.url.encode("%d번 게시물이 수정되었습니다.".formatted(id));
    return "redirect:/article/%d?msg=%s".formatted(id, msg);
}
  • 로그인 권한이 있어야 하기 때문에 @PreAuthorize 어노테이션을 달았다. isAuthenticated() 를 설정하면 로그인한 회원만이 사용할 수 있다.
  • 수정한 이후에는 게시물 수정했습니다가 나오는 url을 반환하도록 했다.

ArticleService.java

public void modify(Article article, String subject, String content) {
        article.setSubject(subject);
        article.setContent(content);
        articleRepository.save(article);
    }

게시물의 이미지 5개 나오도록

🔅th:block

  • th:block을 사용하지 않는다면?
    • 아래와 같이 두 개의 div 태그를 반복문으로 같이 돌리면 문제가 생길 수 있다.
<div th:each="user : ${userList}">
	<span th:text="user.username}">username</span>
    <span th:text="user.age}">age</span>
</div>

<div th:each="user : ${userList}">
	<span th:text="${user.username} + ' & ' + ${user.age}">username&age</span>
</div>
  • th:block 을 사용한다면?
<th:block th:each="user : ${userList}">
    <div>
        <span th:text="user.username}">username</span>
        <span th:text="user.age}">age</span>
    </div>
    <div>
        <span th:text="${user.username} + ' & ' + ${user.age}">username&age</span>
    </div>	
</th:block>

**th:block은 렌더링 될 때 사라지고, 웹브라우저에는 두 개의 <div> 태그의 반복문 결과만 나온다.**

th:block 이용해서 5개의 이미지를 브라우저에 띄우기

modify.html

<th:block th:each="i : ${#numbers.sequence(1, 5)}" th:with="genFile=${article.extra.genFileMap.get('common\_\_inBody\_\_' + i)}">
    <div>
        <span th:text="|${i}번 이미지|"></span>

        <th:block th:if="${genFile != null}">
            <hr>
            <a th:href="@{${genFile.url}}" target="_blank">
                <img class="w-10 h-10 object-cover rounded" title="새창에서 크게 보기" th:src="@{${genFile.url}}" alt="">
                <br>
                <label>
                    <input type="checkbox" value="" th:name="|delete___common\_\_inBody\_\_${i}|">
                    <span>이미지 삭제</span>
                </label>
            </a>
        </th:block>

        <hr>
        <input type="file" th:name="|common\_\_inBody\_\_${i}|"
               accept="image/png, image/gif, image/jpeg">
    </div>
</th:block>
  • 수정 폼에서도 이미지가 5개 나올 수 있게 th:block을 했다.
  • 이미지를 삭제하는 버튼도 생성

write.html

<th:block th:each="i : ${#numbers.sequence(1, 5)}">
    <div>
        <span th:text="|${i}번 이미지|"></span>
        <input type="file" th:name="|common\_\_inBody\_\_${i}|" accept="image/png, image/gif, image/jpeg">
    </div>
</th:block>

수정폼에서 새로운 이미지가 추가되도록

ArticleController.java

@PreAuthorize("isAuthenticated()")
@PostMapping("/{id}/modify")
@ResponseBody
public String modify(@AuthenticationPrincipal MemberContext memberContext, Model model, @PathVariable Long id, @Valid ArticleForm articleForm, **MultipartRequest multipartRequest**) {
    Article article = articleService.getForPrintArticleById(id);

    if (memberContext.memberIsNot(article.getAuthor())) {
        throw new ResponseStatusException(HttpStatus.FORBIDDEN);
    }

    **Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();

    RsData<Map<String, GenFile>> saveFilesRsData = genFileService.saveFiles(article, fileMap);**

    articleService.modify(article, articleForm.getSubject(), articleForm.getContent());

    String msg = Util.url.encode("%d번 게시물이 수정되었습니다.".formatted(id));
    return "redirect:/article/%d?msg=%s".formatted(id, msg);
}
  • 이미지가 수정되고 나면 수정폼에 반영이 되도록 해야하기 때문에 새로운 이미지를 등록하도록 하는 코드를 추가한다.

GenFile에서 수정 로직 구현

public void merge(GenFile other) {
    relTypeCode = other.getRelTypeCode();
    relId = other.getRelId();
    typeCode = other.getTypeCode();
    type2Code = other.getType2Code();
    fileExtTypeCode = other.getFileExtTypeCode();
    fileExtType2Code = other.getFileExtType2Code();
    fileSize = other.getFileSize();
    fileNo = other.getFileNo();
    fileExt = other.getFileExt();
    fileDir = other.getFileDir();
    originFileName = other.getOriginFileName();
}

public String getFilePath() {
    return AppConfig.GET_FILE_DIR_PATH + "/" + getFileDir() + "/" + getFileName();
}
  • 새로운 이미지의 정보들을 GenFile에서 저장하도록 merge 메서드를구현

GenFileService.java

@Transactional
public GenFile save(GenFile genFile) {
    Optional<GenFile> opOldGenFile = genFileRepository.findByRelTypeCodeAndRelIdAndTypeCodeAndType2CodeAndFileNo(genFile.getRelTypeCode(), genFile.getRelId(), genFile.getTypeCode(), genFile.getType2Code(), genFile.getFileNo());

    if (opOldGenFile.isPresent()) {
        GenFile oldGenFile = opOldGenFile.get();
        deleteFileFromStorage(oldGenFile);

        oldGenFile.merge(genFile);

        genFileRepository.save(oldGenFile);

        return oldGenFile;
    }

    genFileRepository.save(genFile);

    return genFile;
}

private void deleteFileFromStorage(GenFile genFile) {
    new File(genFile.getFilePath()).delete();
}
  • 만약 게시글에 이미 이미지가 있다면 이미지를 지우고, db에 이미지를 추가하도록

0개의 댓글