From b906ed74a7106cf1122687db3bea6a380d945561 Mon Sep 17 00:00:00 2001 From: dyhj625 Date: Tue, 4 Mar 2025 17:00:28 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=ED=8C=90=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=EB=8B=A4=EC=9A=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/api/BoardController.java | 57 +++++++++++++++++-- .../localhost/service/FileService.java | 36 ++++++++++++ .../localhost/service/localbordService.java | 11 +++- 3 files changed, 96 insertions(+), 8 deletions(-) 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 4daa7b2..ce62749 100644 --- a/src/main/java/io/company/localhost/controller/api/BoardController.java +++ b/src/main/java/io/company/localhost/controller/api/BoardController.java @@ -16,13 +16,23 @@ 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; +import org.springframework.core.io.UrlResource; +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.multipart.MultipartFile; import com.github.pagehelper.PageInfo; @@ -48,6 +58,7 @@ public class BoardController { private final localbordService boardService; private final commoncodService commoncodService; private final PasswordEncoder passwordEncoder; + /** * 공지사항 목록 조회 @@ -84,7 +95,6 @@ public class BoardController { @PostMapping public ApiResponse createBoard(@ReqMap MapDto map) { - if (map.containsKey("LOCBRDPWD") && !map.getString("LOCBRDPWD").trim().isEmpty()) { // 빈 값 체크 String rawPassword = map.getString("LOCBRDPWD"); String hashedPassword = passwordEncoder.encode(rawPassword); @@ -113,6 +123,34 @@ public class BoardController { return ApiResponse.ok(board); } + + /** + * 파일 다운로드 API + * @param path 파일 경로 + * @return 파일 데이터 (바이너리 응답) + */ + @GetMapping("/download") + public ResponseEntity downloadFile(@RequestParam String path) { + try { + Path filePath = Paths.get(path).normalize(); + Resource resource = new UrlResource(filePath.toUri()); + + if (!resource.exists() || !resource.isReadable()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); + } + + String contentType = Files.probeContentType(filePath); + String fileName = filePath.getFileName().toString(); + + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"") + .header(HttpHeaders.CONTENT_TYPE, contentType != null ? contentType : "application/octet-stream") + .body(resource); + + } catch (IOException e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + } + } /** * 게시물 삭제 @@ -148,13 +186,20 @@ public class BoardController { @Member @ParameterCheck @PostMapping("/{CMNBRDSEQ}/attachments") - public ApiResponse uploadAttachment(@ReqMap MapDto map) { - Long userId = AuthUtil.getUser().getId(); - map.put("CMNFLEREG", userId); - boardService.insertAttachment(map); - return ApiResponse.ok("첨부파일이 저장되었습니다."); + public ApiResponse uploadAttachment(@ReqMap MapDto map, @RequestParam("file") MultipartFile file) { + try { + Long userId = AuthUtil.getUser().getId(); + map.put("CMNFLEREG", userId); + + boardService.insertAttachment(map, file); + + return ApiResponse.ok("첨부파일이 저장되었습니다."); + } catch (Exception e) { + return ApiResponse.ok("첨부파일 저장 실패: " + e.getMessage()); + } } + /** * 게시물, 댓글 좋아요/싫어요 추가 * @ReqMap map 데이터 (LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD, LOCBRDSEQ) diff --git a/src/main/java/io/company/localhost/service/FileService.java b/src/main/java/io/company/localhost/service/FileService.java index 13a7fdc..92f6138 100644 --- a/src/main/java/io/company/localhost/service/FileService.java +++ b/src/main/java/io/company/localhost/service/FileService.java @@ -34,6 +34,9 @@ public class FileService { @Value("${filePath.profile}") private String uploadPath; + @Value("${filePath.boardfile}") + private String boardFilePath; + /** * 파일 업로드 * @@ -65,4 +68,37 @@ public class FileService { throw new RuntimeException("파일 업로드 실패: " + e.getMessage()); } } + + /** + * 게시판 파일 업로드 + * + * @param file + * @return + * @throws RuntimeException + */ + public String boardUploadFile(MultipartFile file) { + try { + System.out.println(file); + // 원본 파일명 + String originalFilename = file.getOriginalFilename(); + // 파일 확장자 + String extension = FilenameUtils.getExtension(originalFilename); + // UUID를 사용하여 고유한 파일명 생성 + String newFilename = UUID.randomUUID().toString() + "." + extension; + + // 최종 저장 경로 생성 (기본경로 + 파일명) + Path targetPath = Paths.get(boardFilePath, newFilename); + // 저장될 디렉토리가 없는 경우 생성 + Files.createDirectories(targetPath.getParent()); + + // 동일 파일명이 있을 경우 덮어쓰기 + Files.copy(file.getInputStream(), targetPath, StandardCopyOption.REPLACE_EXISTING); + + // 저장된 파일의 상대 경로 반환 + return targetPath.toString(); + + } catch (IOException e) { + throw new RuntimeException("파일 업로드 실패: " + e.getMessage()); + } + } } \ 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 e747a7c..01de246 100644 --- a/src/main/java/io/company/localhost/service/localbordService.java +++ b/src/main/java/io/company/localhost/service/localbordService.java @@ -15,11 +15,16 @@ package io.company.localhost.service; 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; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -36,6 +41,7 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public class localbordService { private final localbordMapper boardMapper; + private final FileService fileService; private static final long MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB public List selectNotices(MapDto map) { @@ -78,14 +84,15 @@ public class localbordService { return (BigInteger) map.get("LOCBRDSEQ"); } - public void insertAttachment(MapDto map) { + public void insertAttachment(MapDto map, MultipartFile file) { String boardSeqStr = (String) map.get("CMNBRDSEQ"); Long boardSeq = Long.parseLong(boardSeqStr); map.put("CMNBRDSEQ", boardSeq); String newFilename = UUID.randomUUID().toString(); map.put("CMNFLENAM", newFilename); - + String Path = fileService.boardUploadFile(file); + map.put("CMNFLEPAT", Path); boardMapper.insertAttachment(map); }