
파일 업로드하고 파일의 정보 확인
1. 뷰 변경하기
board\src\main\resources\templates\board\boardWrite.htm
<form id="frm" name="frm" method="post" action="/board/insertBoard.do" enctype=multipart/form-data>
.
.
.
<input type="file" id="files" name="files" multiple="multiple">
1: 폼을 이용해서 데이터를 전송할 때 파일도 같이 첨부될 수 있도록 폼의 enctype 속성을 multipart/form-data 로 지정한다.
또한 폼의 전송 방식은 반드시 post로 지정해야 한다. (파일이 첨부되어 전송되도록 폼의 전송 방식을 post로 지정한다)
5: multiple 속성을 추가하면 하나의 태그에 여러 개의 파일을 첨부할 수 있다. (HTML5 이상에서)
2. 컨트롤러 변경하기
board\src\main\java\board\board\controller\BoardController.java
@RequestMapping("/board/insertBoard.do")
public String insertBoard(BoardDto board, MultipartHttpServletRequest multipartHttpServletRequest) throws Exception{
boardService.insertBoard_433(board, multipartHttpServletRequest);
return "redirect:/board/openBoardList.do";
}
2: MultipartHttpServletRequest 를 파라미터로 추가, MultipartHttpServletRequest 는 ServletRequest를 상속받아 구현된 인터페이스로, 업로드된 파일을 처리하기 위한 여러 가지 메서드를 제공한다.
3-1. 서비스 변경하기
board\src\main\java\board\board\service\BoardService.java
void insertBoard_433(BoardDto board, MultipartHttpServletRequest multipartHttpServletRequest) throws Exception;
3-2. Impl 변경하기
board\src\main\java\board\board\service\BoardServiceImpl.java
@Override
public void insertBoard_433(BoardDto board, MultipartHttpServletRequest multipartHttpServletRequest) throws Exception {
// boardMapper.insertBoard_434(board);
if(ObjectUtils.isEmpty(multipartHttpServletRequest) == false) {
Iterator<String> iterator = multipartHttpServletRequest.getFileNames();
String name;
Logger log = LoggerFactory.getLogger(this.getClass());
while(iterator.hasNext()) {
name = iterator.next();
log.debug("file fag name : "+name);
List<MultipartFile> list = multipartHttpServletRequest.getFiles(name);
for(MultipartFile multipartFile : list) {
log.debug("start file information");
log.debug("file name : "+multipartFile.getOriginalFilename());
log.debug("file size : "+multipartFile.getSize());
log.debug("file content type : "+multipartFile.getContentType());
log.debug("end file information");
}
}
}
}
5: 이터레이터를이용해 파일 태그의 이름을 가져옴. HTML에 있는 name
7: log 출력을 위해 추가함.
4. 결과 확인
파일 서버에 저장하기
1. 첨부파일 DTO 생성
board\src\main\java\board\board\dto\BoardFileDto.java 생성
package board.board.dto;
import lombok.Data;
@Data
public class BoardFileDto {
private int idx;
private int boardIdx;
private String originalFileName;
private String storedFilePath;
private long fileSize;
}
2. 파일 처리를 위한 클래스 생성
board\src\main\java\board\common\FileUtils.java 생성
package board.common;
import java.io.File;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import board.board.dto.BoardFileDto;
@Component
public class FileUtils {
public List<BoardFileDto> parseFileInfo(int boardIdx, MultipartHttpServletRequest multipartHttpServletRequest) throws Exception{
if(ObjectUtils.isEmpty(multipartHttpServletRequest)){
return null;
}
List<BoardFileDto> fileList = new ArrayList<>();
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMMdd");
ZonedDateTime current = ZonedDateTime.now();
String path = "images/"+current.format(format);
File file = new File(path);
if(file.exists() == false){
file.mkdirs();
}
Iterator<String> iterator = multipartHttpServletRequest.getFileNames();
String newFileName, originalFileExtension, contentType;
while(iterator.hasNext()){
List<MultipartFile> list = multipartHttpServletRequest.getFiles(iterator.next());
for (MultipartFile multipartFile : list){
if(multipartFile.isEmpty() == false){
contentType = multipartFile.getContentType();
if(ObjectUtils.isEmpty(contentType)){
break;
}
else{
if(contentType.contains("image/jpeg")) {
originalFileExtension = ".jpg";
}
else if(contentType.contains("image/png")) {
originalFileExtension = ".png";
}
else if(contentType.contains("image/gif")) {
originalFileExtension = ".gif";
}
else{
break;
}
}
newFileName = Long.toString(System.nanoTime()) + originalFileExtension;
BoardFileDto boardFile = new BoardFileDto();
boardFile.setBoardIdx(boardIdx);
boardFile.setFileSize(multipartFile.getSize());
boardFile.setOriginalFileName(multipartFile.getOriginalFilename());
boardFile.setStoredFilePath(path + "/" + newFileName);
fileList.add(boardFile);
file = new File(path + "/" + newFileName);
multipartFile.transferTo(file);
}
}
}
return fileList;
}
}
17: 어노테이션을 이용해 FileUtils 클래스를 스프링의 빈으로 등록
28~33: 파일이 업로드될 폴더를 생성한다. ZoneDateTime 은 오늘 날짜를 확인하기 위해 사용(JDK1.8이상)
43~60: 파일 형식을 확인하고 그에 따라 이미지의 확장자를 지정
62: 서버에 저장될 파일 이름을 생성
63~68: 데이터베이스에 저장할 파일 정보를 BoardFileDto에 저장한다.
70~71: 업로드된 파일을 새로운 이름으로 바꾸어 지정된 경로에 저장한다.
3. 서비스 및 매퍼 변경하기
board\src\main\java\board\board\service\BoardServiceImpl.java
@Autowired
private FileUtils fileUtils;
.
.
.
@Override
public void insertBoard_433(BoardDto board, MultipartHttpServletRequest multipartHttpServletRequest) throws Exception {
boardMapper.insertBoard_434(board);
List<BoardFileDto> list = fileUtils.parseFileInfo(board.getBoardIdx(), multipartHttpServletRequest);
if(CollectionUtils.isEmpty(list) == false){
boardMapper.insertBoardFileList(list);
}
}
9: FileUtils 클래스를 이용해서 업로드된 파일을 서버에 저장하고 파일의 정보를 가져온다.
board\src\main\java\board\board\mapper\BoardMapper.java 추가
void insertBoardFileList(List<BoardFileDto> list) throws Exception;
4.SQL 변경 및 추가하기
board\src\main\resources\mapper\board\sql-board.xml
<insert id="insertBoard_434" parameterType="board.board.dto.BoardDto" useGeneratedKeys="true" keyProperty="boardIdx">
.
.
.
<insert id="insertBoardFileList" parameterType="board.board.dto.BoardFileDto">
<![CDATA[
INSERT INTO t_file
(
board_idx,
original_file_name,
stored_file_path,
file_size,
creator_id,
created_datetime
)
VALUES
]]>
<foreach collection="list" item="item" separator=",">
(
#{item.boardIdx},
#{item.originalFileName},
#{item.storedFilePath},
#{item.fileSize},
'admin',
NOW()
)
</foreach>
</insert>
19: 파일 목록은 하나 이상이기 때문에 마이바티스의 foreach 문을 사용해 collection의 반복 처리를 한다.
5. 결과 확인
첨부된 파일 목록 보여주기
1. SQL 추가하기
<select id="selectBoardFileList" parameterType="int" resultType="board.board.dto.BoardFileDto">
<![CDATA[
SELECT
idx,
board_idx,
original_file_name,
FORMAT(ROUND(file_size / 1024), 0) AS file_size
FROM
t_file
WHERE
board_idx = #{boardIdx}
AND deleted_yn = 'N'
]]>
</select>
2. BoardDto 추가
private List<BoardFileDto> fileList;
3. 서비스 및 매퍼 추가
BoardServiceImpl.java
AS-IS
public BoardDto selectBoardDetail(int boardIdx) throws Exception{
boardMapper.updateHitCount(boardIdx);
BoardDto board = boardMapper.selectBoardDetail(boardIdx);
return board;
}
TO-BE
public BoardDto selectBoardDetail(int boardIdx) throws Exception{
BoardDto board = boardMapper.selectBoardDetail(boardIdx);
List<BoardFileDto> fileList = boardMapper.selectBoardFileList(boardIdx);
board.setFileList(fileList);
boardMapper.updateHitCount(boardIdx);
return board;
}
BoardMapper.java
List<BoardFileDto> selectBoardFileList(int boardIdx) throws Exception;
4. 뷰 추가
<div class="file_list">
<a th:each="list : ${board.fileList}" th:text="|${list.originalFileName} (${list.fileSize} kb)|"></a>
</div>
5. 결과 확인
'Spring Boot > 4. 파일 업로드와 다운로드' 카테고리의 다른 글
파일 다운로드 (0) | 2022.10.31 |
---|---|
파일 첨부를 위한 설정 (0) | 2022.10.31 |