코딩기록 저장소 🐕/기능구현연습

10/27 게시글 첨부파일, 저장, 삭제🐼

kimkongmom 2023. 10. 27. 08:50

 

 

 

 

 

▶ mapper.xml

1️⃣  insertBlog  ➡️ 블로그 데이터 삽입

2️⃣  insertBlogImage ➡️ 블로그 이미지데이터 삽입

3️⃣  getBlogImageInYesterday ➡️ 특정날짜 삽입된 이미지 조회

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 
<mapper namespace="com.gdu.myhome.dao.BlogMapper">
 
  <insert id="insertBlog" parameterType="BlogDto">
    <selectKey order="BEFORE" keyProperty="blogNo" resultType="int">
      SELECT BLOG_SEQ.NEXTVAL
        FROM DUAL
    </selectKey>
    INSERT INTO BLOG_T(
        BLOG_NO
      , TITLE
      , CONTENTS
      , USER_NO
      , IP
      , CREATED_AT
      , MODIFIED_AT
    ) VALUES(
        #{blogNo}
      , #{title}
      , #{contents}
      , #{userNo}
      , #{ip}
      , TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:MI:SS')
      , TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:MI:SS')
    )
  </insert>
  
  <insert id="insertBlogImage" parameterType="BlogImageDto">
    INSERT INTO BLOG_IMAGE_T(
        BLOG_NO
      , IMAGE_PATH
      , FILESYSTEM_NAME
    ) VALUES(
        #{blogNo}
      , #{imagePath}
      , #{filesystemName}
    )
  </insert>
  
  <select id="getBlogImageInYesterday" resultType="BlogImageDto">
    SELECT BLOG_NO, IMAGE_PATH, FILESYSTEM_NAME
      FROM BLOG_IMAGE_T
     WHERE IMAGE_PATH = '/blog/' || TO_CHAR(SYSDATE - 1, 'YYYY/MM/DD')
  </select>
  
  
  
  
  
  
</mapper>
cs

 

 

▶ BlogMapper

 

1
2
3
4
5
6
7
8
 
@Mapper
public interface BlogMapper {
  public int insertBlog(BlogDto blog);
  public int insertBlogImage(BlogImageDto imageDto);
  public List<BlogImageDto> getBlogImageInYesterday();
}
 
cs

 

 

▶BlogService

 

1
2
3
4
5
6
 
public interface BlogService {
  public Map<String, Object> imageUpload(MultipartHttpServletRequest multipartRequest);
  public int addBlog(HttpServletRequest request);
}
 
cs

 

 

▶BlogServiceImpl

imageUpload ➡️ MultipartHttpServletRequest를 통해 이미지를 받아옵니다.

addBlog ➡️ BlogDto 객체를 생성하여 블로그 글 정보를 설정합니다.
blogMapper.insertBlog(blog)를 호출하여 블로그 글을 데이터베이스에 추가하고 결과를 반환합니다.
글 내용(contents)에 포함된 이미지를 파싱하고, 이미지 파일의 정보를 데이터베이스에 저장합니다. 

이미지 태그를 추출하고, 이미지 파일의 경로 및 이름을 데이터베이스에 저장합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package com.gdu.myhome.service;
 
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
 
@RequiredArgsConstructor
@Service
public class BlogServiceImpl implements BlogService {
 
  private final BlogMapper blogMapper;
  private final MyFileUtils myFileUtils;
  
  @Override
  public Map<String, Object> imageUpload(MultipartHttpServletRequest multipartRequest) {
    
    // 이미지가 저장될 경로
    String imagePath = myFileUtils.getBlogImagePath();
    File dir = new File(imagePath);
    if(!dir.exists()) {
      dir.mkdirs();
    }
    // 이미지 파일 (CKEditor는 이미지를 upload라는 이름으로 보냄)
    MultipartFile upload = multipartRequest.getFile("upload");
    
    // 이미지가 저장될 이름
    String originalFilename = upload.getOriginalFilename();
    String filesystemName = myFileUtils.getFilesystemName(originalFilename);
    
    // 이미지 File 객체
    File file = new File(dir, filesystemName);
    
    // 저장
    try {
      upload.transferTo(file);
    }catch (Exception e) {
      e.printStackTrace();
    }
    
    // CKEditor로 저장된 이미지의 경로를 JSON 형식으로 반환해야 함   
    return Map.of("uploaded"true
                , "url", multipartRequest.getContextPath() + imagePath + "/" + filesystemName);
  }
  
  @Override
  public int addBlog(HttpServletRequest request) {
    
    // BLOG_T에 추가할 데이터
    String title = request.getParameter("title");
    String contents = request.getParameter("contents");
    int userNo = Integer.parseInt(request.getParameter("userNo"));
    String ip = request.getRemoteAddr();
 
    // BLOGDTO 생성
    BlogDto blog = BlogDto.builder()
                     .title(title)
                     .contents(contents)
                     .userNo(userNo)
                     .ip(ip)
                     .build();
    // BLOG_T에 추가
    // BlogMapper의 insertBlog() 메서드를 실행하면
    // 메서드로 전달환 blog 객체에 blogNo값이 저장된다.
    int addResult = blogMapper.insertBlog(blog);
    
    // BLOG 작성시 사용한 이미지 목록 (Jsoup 라이브러리 사용)
    Document document = Jsoup.parse(contents);
    Elements elements = document.getElementsByTag("img");
    
    if(elements != null) {
      for(Element element : elements) {
        String src = element.attr("src");
        String filesystemName = src.substring(src.lastIndexOf("/"+ 1);
        BlogImageDto blogImage = BlogImageDto.builder()
                                    .blogNo(blog.getBlogNo())
                                    .imagePath(myFileUtils.getBlogImagePath())
                                    .filesystemName(filesystemName)
                                    .build();
        blogMapper.insertBlogImage(blogImage);
      }
    }
    
    return addResult;
  }
}
 
cs

 

 

▶BlogController

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.gdu.myhome.controller;
 
@RequiredArgsConstructor
@RequestMapping("/blog")
@Controller
public class BlogController {
 
  private final BlogService blogService;
  
  @GetMapping("/list.do")
  public String list(HttpServletRequest request, Model model) {
    return "blog/list";
  }
  
  @GetMapping("/write.form")
  public String write() {
    return "blog/write";
  }
  
  @PostMapping(value ="/imageUpload.do", produces = "application/json")
  @ResponseBody
  public Map<String, Object> imageUpload(MultipartHttpServletRequest multipartRequest){
    return blogService.imageUpload(multipartRequest);
  }
  
  @PostMapping("/addBlog.do")
  public String addBlog(HttpServletRequest request, RedirectAttributes redirectAttributes) {
    int addResult = blogService.addBlog(request);
    redirectAttributes.addFlashAttribute("addResult", addResult);
    return "redirect:/blog/list.do";
  }
}
 
cs

 

 

▶ MyFileUtils

getBlogImagePath() ➡️ 블로그 이미지 파일이 저장될 경로를 반환합니다.

 

getFilesystemName(String originalFileName) ➡️

업로드된 파일의 원래 파일 이름을 받아 해당 파일의 저장될 파일 이름을 반환합니다.
반환 값은 UUID와 확장자를 조합하여 생성됩니다.
originalFileName의 확장자를 추출하여 사용하여 생성합니다.

 

getBlogImagePathInYesterday() ➡️ 어제 날짜에 해당하는 블로그 이미지가 저장될 경로를 반환합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.gdu.myhome.util;
 
@Component
public class MyFileUtils {
 
  // 파일이 저장될 경로 반환하기
  public String getBlogImagePath() {
    /*    /storage/yyyy/MM/dd    */ 
    LocalDate today = LocalDate.now();
    return "/blog/" + DateTimeFormatter.ofPattern("yyyy/MM/dd").format(today);
 }
   // 파일이 저장될 이름 반환하기
   public String getFilesystemName(String originalFileName) {
    
    /* UUID.확장자 */
    
    String extName = null;
    if(originalFileName.endsWith("tar.gz")) {  // 확장자에 마침표가 포함되는 예외 경우를 처리한 
      extName = "tar.gz";
    } else {
      String[] arr = originalFileName.split("\\."); // [.] 또는 \\.
      extName = arr[arr.length - 1];
    }
    return UUID.randomUUID().toString().replace("-"""+ "." + extName;
  }
   
   // 블로그 이미지가 저장된 어제 경로를 반환
   public String getBlogImagePathInYesterday() {
     LocalDate date = LocalDate.now();
     date = date.minusDays(1);
     return "/blog/" + DateTimeFormatter.ofPattern("yyyy/MM/dd").format(date);
   }
}
 
cs

 

 

 

 

블로그