본문 바로가기
[Spring Boot]

[스트링부트] 게시판 첨부파일 기능 구현하기

by 슬쨩! 2024. 1. 31.

  구현 화면

 

 

폼 화면에서 - 이미지 첨부파일 하고 제출시 이후에 detail 에서 나오는 화면

 

 

✅[1단계 : properties 수정]

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybo_db2?serverTimezone=UTC&useSSL=false

spring.datasource.username=root

spring.datasource.password=1234

 

spring.jpa.database=mysql

spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect

spring.jpa.hibernate.ddl-auto=update

spring.jpa.generate-ddl=true

spring.jpa.show-sql=true

 

logging.level.org.hibernate=info

 

#파일 한개 당 최대사이즈

spring.servlet.multipart.maxFileSize=20MB

#요청당 최대 파일 크기

spring.servlet.multipart.maxRequestSize=100MB

#상품 이미지 업로드 경로

ImgLocation=D:/c402/sts4/upload3

#리소스 업로드 경로

uploadPath=file:///D:/c402/sts4/upload3/

 

 

spring.servlet.multipart.enabled=true

 

 

 

[2단계 : Question 컬럼 추가하기]

private String filepath;/*파일저장경로*/

private String filename;/*파일이름*/

 

 

[3단계 : form.html 수정하기]

-. enctype 선언하기
<form th:object="${questionForm}" method="post" enctype="multipart/form-data">

-. input type="file name="file" 작성하기

<div class="mb-3">

<label for="subject" class="form-label">제목</label>

<input type="text" th:field="*{subject}" name="subject" class="form-control">

</div>

<div class="mb-3">

<label for="content" class="form-label">내용</label>

<textarea name="content" th;field="*{content}" class="form-control" rows="10"></textarea>

</div>

<table>

<tr>

<td><input type="file" name="file" /></td>

</tr>

</table>

 

<input type="submit" value="저장하기" class="btn btn-primary my-2">

</form>


[4단계 : Controller 수정하기] - form이 submit될때 로직을 처리 해줌
-. QuestionForm 객체를 통해 사용자의 입력 데이터를 받아오고, BindingResult를 통해 유효성 검사 결과를 확인합니다. Principal 객체는 현재 사용자의 정보를 제공하며, @RequestParam("file") MultipartFile file은 업로드된 파일을 받아온다.

@PreAuthorize("isAuthenticated()")

@PostMapping("/create")

public String questionCreate(@Valid QuestionForm questionForm, BindingResult bindingResult, Principal principal, @RequestParam("file") MultipartFile file) throws Exception{

if (bindingResult.hasErrors()) {

return "question_form";

}

SiteUser siteUser = this.userService.getUser(principal.getName());

this.questionService.create(questionForm.getSubject(), questionForm.getContent(), siteUser, questionForm.getCategory(), file);

return "redirect:/question/list";

}

 

-. this.questionService.create(questionForm.getSubject(), questionForm.getContent(), siteUser, questionForm.getCategory(), file);: questionService를 통해 새로운 질문을 생성합니다. questionForm에서 주제, 내용, 사용자, 카테고리 및 업로드된 파일 등의 정보를 전달

 

 

[5단계 : Service  컬럼 추가하기]
-. properties에 미리 설정해둔 ImgLocation의 저장 위치를 설정해줌.

@Value("${ImgLocation}")

private String imgLocation;

public void create(String subject, String content, SiteUser user, String category, MultipartFile file) throws Exception{

 

String projectPath = imgLocation; //파일저장위치 = projectPath

 

UUID uuid = UUID.randomUUID(); //식별자.랜덤으로 이름만들어줌

String fileName = uuid + "_" + file.getOriginalFilename(); //저장될파일이름지정=랜덤식별자_원래파일이름

File saveFile = new File(projectPath, fileName); //빈껍데기생성 이름은 fileName, projectPath라는 경로에담김

file.transferTo(saveFile);

 

Question q=new Question();

q.setSubject(subject);

q.setContent(content);

q.setCreateDate(LocalDateTime.now());

q.setAuthor(user);

q.setCategory(category);

/*파일 업로드 추가*/

q.setFilename(fileName);//파일이름

q.setFilepath(projectPath + fileName); //저장경로,파일이름

this.questionRepository.save(q);

 

}

 

-. DB에 폼 데이터를 저장하는 로직

 

[6단계 : WebMvcConfig.java파일 생성하기]

@Configuration

public class WebMvcConfig implements WebMvcConfigurer {

 

//uploadPath프로퍼티값을 읽어온다

@Value("${uploadPath}")

String uploadPath;

 

@Override

public void addResourceHandlers(ResourceHandlerRegistry registry) {

registry.addResourceHandler("/photo/**")

//웹브라우저에 입력하는 url에 /photo 로 시작하는 경우 uploadPath에 설정한 폴더 기준으로 파일을 읽어오도록 설정

 

.addResourceLocations(uploadPath);

//로컬컴퓨터에 저장된 파일을 읽어올 root경로

}

}

이 코드는 Spring MVC 프로젝트에서 정적 리소스(예: 이미지 파일)를 처리하기 위한 설정 클래스인 WebMvcConfig입니다. 여기서 addResourceHandlers 메소드를 사용하여 정적 리소스의 핸들러를 추가하고, 이를 통해 해당 리소스의 위치를 지정합니다.

  1. @Configuration: 이 어노테이션은 해당 클래스가 Spring 설정 클래스임을 나타냅니다.
  2. WebMvcConfig implements WebMvcConfigurer: WebMvcConfigurer 인터페이스를 구현한 클래스로, Spring MVC의 설정을 커스터마이징할 수 있게 해줍니다.
  3. @Value("${uploadPath}"): 프로퍼티 파일에서 uploadPath라는 키에 대응하는 값을 읽어옵니다. 이는 정적 리소스의 저장 경로를 나타냅니다.
  4. addResourceHandlers(ResourceHandlerRegistry registry): 이 메소드는 정적 리소스 핸들러를 추가하는 역할을 합니다. ResourceHandlerRegistry를 사용하여 어떤 URL 패턴으로 시작하는 요청이 정적 리소스로 처리될지 설정합니다.
    • registry.addResourceHandler("/photo/**"): "/photo"로 시작하는 URL 패턴을 정적 리소스로 처리하도록 설정합니다.
    • addResourceLocations(uploadPath): 해당 URL 패턴으로 들어온 요청이 처리될 정적 리소스의 위치를 설정합니다. 즉, uploadPath에 지정된 디렉토리에서 해당 리소스를 찾아오게 됩니다.

이렇게 설정된 핸들러를 통해 "/photo"로 시작하는 URL 요청이 프로퍼티 파일에서 지정한 uploadPath 디렉토리에서 정적 리소스를 찾아 제공할 수 있습니다.

 

[7단계 : detail.html파일 수정하기] - 출력될 데이터 값 가져오기

<!-- 질문 -->

<div class="border-bottom py-2" th:text="${question.category}"></div>

<h2 class="border-bottom py-2" th:text="${question.subject}"></h2>

<div class="card my-3">

<div class="card-body">

<div class="detail-img">

<img onerror="this.style.visibility='hidden'" th:src="@{|/photo/${question.filename}|}"/>

</div>

<div th:text="${question.content}"></div>

-. th:src="@{/photo/${question.filename}|}"
 이미지를 표시하는 <img> 태그입니다. th:src 속성을 통해 서버에서 받아온 question.filename 값을 사용하여 이미지의 경로를 동적으로 지정합니다. 또한, onerror 속성을 사용하여 이미지 로딩에 실패할 경우 이미지를 숨기도록 처리하고 있습니다.


✅ 실제 Form화면 및 구현