From 4490655eabdb414b0ee1eb39717ca2c01fa27ce9 Mon Sep 17 00:00:00 2001 From: nevermoregb Date: Fri, 7 Mar 2025 10:19:32 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EA=B4=80=EB=A0=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/api/BoardController.java | 27 ++-- .../localhost/mapper/localbordMapper.java | 8 +- .../localhost/service/FileService.java | 38 +++++ .../localhost/service/localbordService.java | 66 +++++++- .../io/company/localhost/utils/FileUtil.java | 147 ++++++++++++++++++ .../io/company/localhost/vo/UploadFile.java | 15 ++ src/main/resources/mapper/localbordMapper.xml | 47 ++++++ 7 files changed, 332 insertions(+), 16 deletions(-) create mode 100644 src/main/java/io/company/localhost/utils/FileUtil.java create mode 100644 src/main/java/io/company/localhost/vo/UploadFile.java diff --git a/src/main/java/io/company/localhost/controller/api/BoardController.java b/src/main/java/io/company/localhost/controller/api/BoardController.java index ce62749..e07cf66 100644 --- a/src/main/java/io/company/localhost/controller/api/BoardController.java +++ b/src/main/java/io/company/localhost/controller/api/BoardController.java @@ -15,14 +15,12 @@ package io.company.localhost.controller.api; -import java.io.File; import java.io.IOException; import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Base64; import java.util.List; import org.springframework.core.io.Resource; @@ -31,7 +29,15 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.github.pagehelper.PageInfo; @@ -165,18 +171,21 @@ public class BoardController { return ApiResponse.ok("게시물이 삭제되었습니다."); } + /** * 게시물 수정 - * @ReqMap map 수정 데이터 (LOCBRDTTL, LOCBRDCON, LOCBRDSEQ) - * @return 수정 결과 메시지 + * + * @param map 수정 데이터 (LOCBRDTTL, LOCBRDCON, LOCBRDSEQ, delListInfo) + * @param files 첨부파일 정보 + * @return + * @throws IOException */ @Member - @ParameterCheck @PutMapping("/{boardId}") - public ApiResponse updateBoard(@ReqMap MapDto map) { - boardService.updateBoard(map); - return ApiResponse.ok("게시물이 수정되었습니다."); + public ApiResponse updateBoard(@ReqMap MapDto map, @RequestPart(value = "files", required = false) List files) throws IOException { + return boardService.updateBoardWithFiles(map, files); } + /** * 첨부파일 추가 diff --git a/src/main/java/io/company/localhost/mapper/localbordMapper.java b/src/main/java/io/company/localhost/mapper/localbordMapper.java index 36d5e72..b74911c 100644 --- a/src/main/java/io/company/localhost/mapper/localbordMapper.java +++ b/src/main/java/io/company/localhost/mapper/localbordMapper.java @@ -42,7 +42,7 @@ public interface localbordMapper { void deleteCommentsByBoardId(MapDto map); // 게시물 수정 - void updateBoard(MapDto map); + int updateBoard(MapDto map); // 기존 반응 조회 MapDto selectReaction(MapDto map); @@ -100,6 +100,12 @@ public interface localbordMapper { //댓글id 확인 MapDto selectCommentById(int commentId); + + void insertAttachments(MapDto map); + + List selectDelFileInfo(String[] array); + + void deleteFileInfo(String[] array); } diff --git a/src/main/java/io/company/localhost/service/FileService.java b/src/main/java/io/company/localhost/service/FileService.java index 92f6138..d9d110d 100644 --- a/src/main/java/io/company/localhost/service/FileService.java +++ b/src/main/java/io/company/localhost/service/FileService.java @@ -19,11 +19,15 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.util.List; import java.util.UUID; import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; + +import io.company.localhost.utils.FileUtil; +import io.company.localhost.vo.UploadFile; import lombok.RequiredArgsConstructor; @Service @@ -37,6 +41,8 @@ public class FileService { @Value("${filePath.boardfile}") private String boardFilePath; + private final FileUtil fileUtil; + /** * 파일 업로드 * @@ -101,4 +107,36 @@ public class FileService { throw new RuntimeException("파일 업로드 실패: " + e.getMessage()); } } + + /** + * 게시판 다중파일 업로드 + * + * @param files + * @return + * @throws IOException + */ + public List boardUploadFiles(List files) throws IOException { + return fileUtil.uploadFiles(boardFilePath, files); + } + + /** + * 파일 삭제 + * + * @param path 경로+파일명 + * @return + */ + public boolean removeFile(String path) { + return fileUtil.removeFile(path); + } + + /** + * 파일 삭제 + * + * @param path + * @param fileName + * @return + */ + public boolean removeFile(String path, String fileName) { + return fileUtil.removeFile(path, fileName); + } } \ No newline at end of file diff --git a/src/main/java/io/company/localhost/service/localbordService.java b/src/main/java/io/company/localhost/service/localbordService.java index 5b71d72..cb5b4c8 100644 --- a/src/main/java/io/company/localhost/service/localbordService.java +++ b/src/main/java/io/company/localhost/service/localbordService.java @@ -14,14 +14,11 @@ *************************************************************/ package io.company.localhost.service; +import java.io.IOException; import java.math.BigInteger; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; import java.util.UUID; -import io.company.localhost.utils.BlobUtil; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -31,10 +28,13 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; +import io.company.localhost.common.dto.ApiResponse; import io.company.localhost.common.dto.MapDto; import io.company.localhost.mapper.localbordMapper; import io.company.localhost.utils.AuthUtil; +import io.company.localhost.utils.BlobUtil; import io.company.localhost.utils.PageUtil; +import io.company.localhost.vo.UploadFile; import lombok.RequiredArgsConstructor; @Service @@ -123,8 +123,8 @@ public class localbordService { boardMapper.deleteBoard(map); } - public void updateBoard(MapDto map) { - boardMapper.updateBoard(map); + public int updateBoard(MapDto map) { + return boardMapper.updateBoard(map); } public void procReactToBoard(MapDto map) { @@ -338,4 +338,58 @@ public class localbordService { } } + /** + * 게시판 수정 + * + * @param map + * @param files + * @throws IOException + */ + @Transactional + public ApiResponse updateBoardWithFiles(MapDto map, List files) throws IOException { + int result = this.updateBoard(map); // 게시글 수정 + Long userId = AuthUtil.getUser().getId(); + + if(result == 1) { + if(files != null && !files.isEmpty()) { + List list = fileService.boardUploadFiles(files); // 파일 업로드 + map.put("CMNFLEREG", userId); + map.put("list", list); + boardMapper.insertAttachments(map); + } + + if(map.get("delFileIdx") != null) { + String[] array = String.valueOf(map.get("delFileIdx")).split(","); + List delListInfo = this.selectDelFileInfo(array); // 삭제 정보 조회 + for(String item : delListInfo) { + fileService.removeFile(item); // 파일 삭제 + } + this.deleteFileInfo(array); // db 데이터 삭제 + } + } else { + return ApiResponse.ok("게시물이 수정에 실패하였습니다."); + } + + return ApiResponse.ok("게시물이 수정되었습니다."); + } + + /** + * 첨부파일 데이터 삭제 + * + * @param array + */ + private void deleteFileInfo(String[] array) { + boardMapper.deleteFileInfo(array); + } + + /** + * 삭제 첨부파일 정보 조회 + * + * @param array + * @return + */ + private List selectDelFileInfo(String[] array) { + return boardMapper.selectDelFileInfo(array); + } + } \ No newline at end of file diff --git a/src/main/java/io/company/localhost/utils/FileUtil.java b/src/main/java/io/company/localhost/utils/FileUtil.java new file mode 100644 index 0000000..1eca685 --- /dev/null +++ b/src/main/java/io/company/localhost/utils/FileUtil.java @@ -0,0 +1,147 @@ +package io.company.localhost.utils; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import io.company.localhost.vo.UploadFile; +import lombok.extern.slf4j.Slf4j; + +@Component +@Slf4j +public class FileUtil { + + /** + * 파일 저장 경로/파일명 + * @param savePath + * @param fileName + * @return + */ + public String getFullPath(String savePath, String fileName) { + return Paths.get(savePath, fileName).toString(); + } + + /** + * DB에 저장될 파일명 + * @param originalFilename + * @return + */ + public String createSaveFileName(String originalFilename) { + String uuid = UUID.randomUUID().toString(); + String extension = getFileExtension(originalFilename); + + return uuid + "." + extension; + } + + + /** + * 파일 확장자 + * @param originalFileName + * @return + */ + public String getFileExtension(String originalFileName) { + int pos = originalFileName.lastIndexOf("."); + + return originalFileName.substring(pos + 1); + } + + /** + * 파일 확장자 제외 + * @param + * @return + */ + public String excludeFileExtension(String withExt) { + int pos = withExt.lastIndexOf("."); + + return withExt.substring(0, pos); + } + + + /** + * 단일 파일 업로드 + * @param savePath + * @param multipartFile + * @return + * @throws IOException + */ + public UploadFile uploadFile(String savePath, MultipartFile multipartFile) throws IOException{ + File saveDirectory = new File(savePath); + + if(!saveDirectory.exists()) saveDirectory.mkdirs(); + if(multipartFile.isEmpty()) return null; + + String originalFileName = multipartFile.getOriginalFilename(); //원본파일명 + String saveFileName = createSaveFileName(originalFileName); //난수명 + String ext = getFileExtension(originalFileName); //확장자 + Long size = multipartFile.getSize(); //사이즈 + String filePath = getFullPath(savePath, saveFileName); + + multipartFile.transferTo(new File(filePath)); + + String orgFileName = this.excludeFileExtension(originalFileName); + String savFileName = this.excludeFileExtension(saveFileName); + + return new UploadFile(orgFileName, savFileName, ext, size, filePath); + } + + /** + * 다중 파일 업로드 + * @param savePath + * @param multipartFiles + * @return + * @throws IOException + */ + public List uploadFiles(String savePath, List multipartFiles) throws IOException{ + List uploadFiles = new ArrayList<>(); + + for(MultipartFile multipartFile : multipartFiles) { + if(!multipartFile.isEmpty()) { + uploadFiles.add(uploadFile(savePath, multipartFile)); + } + } + return uploadFiles; + } + + /** + * 업로드된 파일 삭제 + * @param path + * @param originalProfile + * @return + */ + public Boolean removeFile(String path, String saveFileName) { + log.debug("========================================"); + log.debug("FileUtil.removeFile()"); + log.debug("path : {}", path); + log.debug("saveFileName : {}", saveFileName); + + File file = new File(path, saveFileName); + System.gc(); + boolean result = file.delete(); + + log.debug("result : {}", result); + log.debug("========================================"); + + return result; + } + + public Boolean removeFile(String path) { + log.debug("========================================"); + log.debug("FileUtil.removeFile()"); + log.debug("path : {}", path); + + File file = new File(path); + System.gc(); + boolean result = file.delete(); + + log.debug("result : {}", result); + log.debug("========================================"); + + return result; + } +} diff --git a/src/main/java/io/company/localhost/vo/UploadFile.java b/src/main/java/io/company/localhost/vo/UploadFile.java new file mode 100644 index 0000000..d1ea2bc --- /dev/null +++ b/src/main/java/io/company/localhost/vo/UploadFile.java @@ -0,0 +1,15 @@ + +package io.company.localhost.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class UploadFile { + private String originalFileName; + private String saveFileName; + private String extension; + private long fileSize; + private String filePath; +} diff --git a/src/main/resources/mapper/localbordMapper.xml b/src/main/resources/mapper/localbordMapper.xml index 0c9ea8a..ab64ff2 100644 --- a/src/main/resources/mapper/localbordMapper.xml +++ b/src/main/resources/mapper/localbordMapper.xml @@ -65,6 +65,30 @@ ) + + + INSERT INTO commonfil ( + CMNBRDSEQ, + CMNFLENAM, + CMNFLEORG, + CMNFLEPAT, + CMNFLEEXT, + CMNFLESIZ, + CMNFLEREG, + CMNFLERDT + ) VALUES + + #{LOCBRDSEQ}, + #{item.saveFileName}, + #{item.originalFileName}, + #{item.filePath}, + #{item.extension}, + #{item.fileSize}, + #{CMNFLEREG}, + NOW() + + + + + + + + + DELETE FROM + commonfil + WHERE + CMNFLESEQ in + + #{item} + +