본문 바로가기
Java/Spring

Spring) 게시글 작성 - 파일 업로드 처리를 위한 설정

by 박채니 2022. 8. 30.
안녕하세요, 코린이의 코딩 학습기 채니 입니다.
개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.

 

글쓰기 폼

 

Controller

BoardController

@GetMapping("/boardForm.do")
public void boardForm() {}

 

boardForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<jsp:include page="/WEB-INF/views/common/header.jsp">
	<jsp:param value="게시글 작성" name="title"/>
</jsp:include>
<style>
div#board-container{width:400px; margin:0 auto; text-align:center;}
div#board-container input{margin-bottom:15px;}
/* 부트스트랩 : 파일라벨명 정렬*/
div#board-container label.custom-file-label{text-align:left;}
</style>

<div id="board-container">
	<form name="boardFrm" action="${pageContext.request.contextPath}/board/boardEnroll.do" method="post">
		<input type="text" class="form-control" placeholder="제목" name="title" id="title" required>
		<input type="text" class="form-control" name="memberId" value="${loginMember.memberId}" readonly required>
		<!-- input:file소스 : https://getbootstrap.com/docs/4.1/components/input-group/#custom-file-input -->
		<div class="input-group mb-3" style="padding:0px;">
		  <div class="input-group-prepend" style="padding:0px;">
		    <span class="input-group-text">첨부파일1</span>
		  </div>
		  <div class="custom-file">
		    <input type="file" class="custom-file-input" name="upFile" id="upFile1" >
		    <label class="custom-file-label" for="upFile1">파일을 선택하세요</label>
		  </div>
		</div>
		
	    <textarea class="form-control" name="content" placeholder="내용" required></textarea>
		<br />
		<input type="submit" class="btn btn-outline-success" value="저장" >
	</form>
</div>
<script>
document.querySelectorAll("[name=upFile]").forEach((input) => {
	input.addEventListener('change', (e) => {
		const {files} = e.target;
		const label = e.target.nextElementSibling;
		
		if(files[0]) {
			label.textContent = files[0].name;
		} else {
			label.textContent = '파일을 선택하세요';
		}
	});
});
</script>
<jsp:include page="/WEB-INF/views/common/footer.jsp"></jsp:include>

 

interceptor 처리

servlet-context.xml

<interceptor>
    <mapping path="/member/memberDetail.do"/>
    <mapping path="/member/memberUpdate.do"/>
    <mapping path="/board/**"/>
    <exclude-mapping path="/board/boardList.do"/>
    <beans:bean id="loginInterceptor" class="com.ce.spring2.common.interceptor.LoginInterceptor"></beans:bean>
</interceptor>

/board/**의 모든 요청을 적용하지만, /board/boardList.do는 제외하도록 하였습니다.

 

Dto

Attachment

@Data
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
public class Attachment {
	private int no;
	private int boardNo;
	@NonNull
	private String originalFilename;
	@NonNull
	private String renamedFilename;
	private int downloadCount;
	private LocalDateTime createdAt;
}

 

Board

@Data
@NoArgsConstructor
@ToString(callSuper = true)
public class Board extends BoardEntity {
	private int attachCount;
	private List<Attachment> attachments = new ArrayList<>();

	public Board(int no, String title, String memberId, String content, int readCount, LocalDateTime createdAt,
			LocalDateTime updatedAt, int attachCount) {
		super(no, title, memberId, content, readCount, createdAt, updatedAt);
		this.attachCount = attachCount;
	}
	
	public void add(Attachment attachment) {
		this.attachments.add(attachment);
	}
}

추후 Attachment를 쉽게 add처리 하기 위해 add()메소드를 생성하였습니다.


파일 업로드 처리를 위한 설정

 

#10 파일 업로드용 의존

pom.xml

<!-- #10 파일 업로드용 의존 -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
</dependency>

 

#10.1 multipartResolver 등록

- 작성된 내용이 multipart이고 파일이 전송되었다면, 먼저 읽어서 자바 메모리 상에 올려놓는 역할

servlet-context.xml

<!-- #10.1 multipartResolver 등록 -->
<!-- 작성된 내용이 multipart이고 파일이 전송되었다면 그걸 먼저 읽어서 자바메모리상에 올려놓음! -->
<!-- 용량을 적지 않으면 무제한 제공 => 서버 터짐! -->
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <beans:property name="maxUploadSize" value="52428800"></beans:property> <!-- 50mb 한건의 파일요청 시 첨부할 파일들의 총 용량 -->
    <beans:property name="maxUploadSizePerFile" value="10245760"></beans:property> <!-- 10mb 한 건의 파일 당 용량 -->
    <beans:property name="maxInMemorySize" value="10240"></beans:property> <!-- 10kb 이상이면 임시파일을 생성해서 관리 -->
</beans:bean>

maxUploadSize - 한 건의 파일요청 시 첨부할 파일들의 총 용량

maxUploadSizePerFile - 한 건의 파일 당 용량

maxInMemorySize - 지정한 용량 이상이면 임시파일을 생성하여 관리

 

boardForm.jsp

<form name="boardFrm" action="${pageContext.request.contextPath}/board/boardEnroll.do" method="post" enctype="multipart/form-data">
    <input type="text" class="form-control" placeholder="제목" name="title" id="title" required>
    <input type="text" class="form-control" name="memberId" value="${loginMember.memberId}" readonly required>
    <!-- input:file소스 : https://getbootstrap.com/docs/4.1/components/input-group/#custom-file-input -->
    <div class="input-group mb-3" style="padding:0px;">
      <div class="input-group-prepend" style="padding:0px;">
        <span class="input-group-text">첨부파일1</span>
      </div>
      <div class="custom-file">
        <input type="file" class="custom-file-input" name="upFile" id="upFile1" multiple>
        <label class="custom-file-label" for="upFile1">파일을 선택하세요</label>
      </div>
    </div>

    <div class="input-group mb-3" style="padding:0px;">
      <div class="input-group-prepend" style="padding:0px;">
        <span class="input-group-text">첨부파일2</span>
      </div>
      <div class="custom-file">
        <input type="file" class="custom-file-input" name="upFile" id="upFile2" multiple>
        <label class="custom-file-label" for="upFile2">파일을 선택하세요</label>
      </div>
    </div>

enctype="multipart/form-data" 속성을 지정하였고, 하나의 input태그에서 여러개의 파일을 등록할 수 있도록 multiple 속성을 추가하였습니다.

 

첨부파일1 - 2개 / 첨부파일2 - 3개

 

Controller

BoardController

@PostMapping("/boardEnroll.do")
public String boardEnroll(Board board, @RequestParam(name = "upFile") List<MultipartFile> upFileList) {
    log.debug("board = {}", board);

    for(MultipartFile upFile : upFileList) {
        log.debug("upFile = {}", upFile);
        log.debug("upFile#name = {}", upFile.getName());
        log.debug("upFile#originalFilename = {}", upFile.getOriginalFilename());
        log.debug("upFile#size = {}", upFile.getSize());
    }

    return "redirect:/board/boardForm.do";
}

@콘솔출력값
DEBUG: com.ce.spring2.board.controller.BoardController - board = Board(super=BoardEntity(no=0, title=abc, memberId=honggd, content=def, readCount=0, createdAt=null, updatedAt=null), attachCount=0, attachments=null)
DEBUG: com.ce.spring2.board.controller.BoardController - upFile = org.springframework.web.multipart.commons.CommonsMultipartFile@27657701
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#name = upFile
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#originalFilename = 2022-02-24.png
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#size = 378710
DEBUG: com.ce.spring2.board.controller.BoardController - upFile = org.springframework.web.multipart.commons.CommonsMultipartFile@7163ff7d
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#name = upFile
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#originalFilename = 2022-03-03.png
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#size = 386814
DEBUG: com.ce.spring2.board.controller.BoardController - upFile = org.springframework.web.multipart.commons.CommonsMultipartFile@3a32114
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#name = upFile
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#originalFilename = 캠핑장 양도 시퀀스(최종).mdj
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#size = 284257
DEBUG: com.ce.spring2.board.controller.BoardController - upFile = org.springframework.web.multipart.commons.CommonsMultipartFile@2f79759d
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#name = upFile
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#originalFilename = 회원 유스케이스(최종).mdj
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#size = 315447
DEBUG: com.ce.spring2.board.controller.BoardController - upFile = org.springframework.web.multipart.commons.CommonsMultipartFile@27aecdc
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#name = upFile
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#originalFilename = 관리자 유스케이스(최종).mdj
DEBUG: com.ce.spring2.board.controller.BoardController - upFile#size = 189384

총 5개의 파일의 정보가 잘 출력되는 것을 확인할 수 있습니다.