게시판 파일다운 추가

This commit is contained in:
dyhj625 2025-03-04 17:00:28 +09:00
parent 02e2b593f7
commit b906ed74a7
3 changed files with 96 additions and 8 deletions

View File

@ -16,13 +16,23 @@
package io.company.localhost.controller.api; package io.company.localhost.controller.api;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.math.BigInteger; 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.ArrayList;
import java.util.Base64;
import java.util.List; 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.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
@ -49,6 +59,7 @@ public class BoardController {
private final commoncodService commoncodService; private final commoncodService commoncodService;
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
/** /**
* 공지사항 목록 조회 * 공지사항 목록 조회
* @ReqMap map 요청 파라미터 (searchKeyword) * @ReqMap map 요청 파라미터 (searchKeyword)
@ -84,7 +95,6 @@ public class BoardController {
@PostMapping @PostMapping
public ApiResponse<BigInteger> createBoard(@ReqMap MapDto map) { public ApiResponse<BigInteger> createBoard(@ReqMap MapDto map) {
if (map.containsKey("LOCBRDPWD") && !map.getString("LOCBRDPWD").trim().isEmpty()) { // 체크 if (map.containsKey("LOCBRDPWD") && !map.getString("LOCBRDPWD").trim().isEmpty()) { // 체크
String rawPassword = map.getString("LOCBRDPWD"); String rawPassword = map.getString("LOCBRDPWD");
String hashedPassword = passwordEncoder.encode(rawPassword); String hashedPassword = passwordEncoder.encode(rawPassword);
@ -114,6 +124,34 @@ public class BoardController {
return ApiResponse.ok(board); return ApiResponse.ok(board);
} }
/**
* 파일 다운로드 API
* @param path 파일 경로
* @return 파일 데이터 (바이너리 응답)
*/
@GetMapping("/download")
public ResponseEntity<Resource> 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();
}
}
/** /**
* 게시물 삭제 * 게시물 삭제
* @ReqMap map 수정 데이터 (LOCBRDSEQ) * @ReqMap map 수정 데이터 (LOCBRDSEQ)
@ -148,13 +186,20 @@ public class BoardController {
@Member @Member
@ParameterCheck @ParameterCheck
@PostMapping("/{CMNBRDSEQ}/attachments") @PostMapping("/{CMNBRDSEQ}/attachments")
public ApiResponse<String> uploadAttachment(@ReqMap MapDto map) { public ApiResponse<String> uploadAttachment(@ReqMap MapDto map, @RequestParam("file") MultipartFile file) {
Long userId = AuthUtil.getUser().getId(); try {
map.put("CMNFLEREG", userId); Long userId = AuthUtil.getUser().getId();
boardService.insertAttachment(map); map.put("CMNFLEREG", userId);
return ApiResponse.ok("첨부파일이 저장되었습니다.");
boardService.insertAttachment(map, file);
return ApiResponse.ok("첨부파일이 저장되었습니다.");
} catch (Exception e) {
return ApiResponse.ok("첨부파일 저장 실패: " + e.getMessage());
}
} }
/** /**
* 게시물, 댓글 좋아요/싫어요 추가 * 게시물, 댓글 좋아요/싫어요 추가
* @ReqMap map 데이터 (LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD, LOCBRDSEQ) * @ReqMap map 데이터 (LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD, LOCBRDSEQ)

View File

@ -34,6 +34,9 @@ public class FileService {
@Value("${filePath.profile}") @Value("${filePath.profile}")
private String uploadPath; private String uploadPath;
@Value("${filePath.boardfile}")
private String boardFilePath;
/** /**
* 파일 업로드 * 파일 업로드
* *
@ -65,4 +68,37 @@ public class FileService {
throw new RuntimeException("파일 업로드 실패: " + e.getMessage()); 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());
}
}
} }

View File

@ -15,11 +15,16 @@
package io.company.localhost.service; package io.company.localhost.service;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import io.company.localhost.utils.BlobUtil; import io.company.localhost.utils.BlobUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; 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.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -36,6 +41,7 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor
public class localbordService { public class localbordService {
private final localbordMapper boardMapper; private final localbordMapper boardMapper;
private final FileService fileService;
private static final long MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB private static final long MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
public List<MapDto> selectNotices(MapDto map) { public List<MapDto> selectNotices(MapDto map) {
@ -78,14 +84,15 @@ public class localbordService {
return (BigInteger) map.get("LOCBRDSEQ"); return (BigInteger) map.get("LOCBRDSEQ");
} }
public void insertAttachment(MapDto map) { public void insertAttachment(MapDto map, MultipartFile file) {
String boardSeqStr = (String) map.get("CMNBRDSEQ"); String boardSeqStr = (String) map.get("CMNBRDSEQ");
Long boardSeq = Long.parseLong(boardSeqStr); Long boardSeq = Long.parseLong(boardSeqStr);
map.put("CMNBRDSEQ", boardSeq); map.put("CMNBRDSEQ", boardSeq);
String newFilename = UUID.randomUUID().toString(); String newFilename = UUID.randomUUID().toString();
map.put("CMNFLENAM", newFilename); map.put("CMNFLENAM", newFilename);
String Path = fileService.boardUploadFile(file);
map.put("CMNFLEPAT", Path);
boardMapper.insertAttachment(map); boardMapper.insertAttachment(map);
} }