본문 바로가기
Java/Spring

Spring) 파일 업로드 처리

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

 

파일 업로드 처리

 

a. 서버 컴퓨터 저장

// spring의 빈으로 등록 되어있음
@Autowired
ServletContext application;

@PostMapping("/boardEnroll.do")
public String boardEnroll(Board board, @RequestParam(name = "upFile") List<MultipartFile> upFileList, RedirectAttributes redirectAttr) throws IllegalStateException, IOException {
    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());

        // 파일이 없어도 빈 객체가 넘어오므로 분기처리!
        if(!upFile.isEmpty()) {				
            // a. 서버컴퓨터 저장
            String saveDirectory = application.getRealPath("/resources/upload/board");
            String renamedFilename = HelloSpringUtils.getRenamedFilename(upFile.getOriginalFilename()); // 20220830_141822222_123.txt
            File destFile = new File(saveDirectory, renamedFilename); // 해당 경로에 해당 이름을 가진 파일객체
            upFile.transferTo(destFile); // 해당 경로에 파일을 저장

ServletContext는 빈으로 등록 되어있기 때문에 의존 주입 받아 사용하였습니다.

저장 위치를 "/resource/upload/board"로 지정해주었으며, 커스텀 파일명을 생성하여 해당 경로에 해당 이름을 가진 파일을 저장하였습니다.

 

HelloSpringUtils

getRenamedFilename()

public static String getRenamedFilename(String originalFilename) {
    // 확장자 추출
    int beginIndex = originalFilename.lastIndexOf(".");
    String ext = "";
    if(beginIndex > -1) {
        ext = originalFilename.substring(beginIndex); // .txt
    }

    // 새이름 생성
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmssSSS_");
    DecimalFormat df = new DecimalFormat("000");
    return sdf.format(new Date()) + df.format(Math.random()*1000) + ext;
}

 

b. DB 저장을 위한 Attachment 객체 생성

        // b. DB저장을 위해 Attachment객체 생성
        Attachment attachment = new Attachment(upFile.getOriginalFilename(), renamedFilename);
        board.add(attachment);
    }
}

log.debug("board = {}", board);

@콘솔출력값
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=[Attachment(no=0, boardNo=0, originalFilename=캠핑장 양도 시퀀스(최종).mdj, renamedFilename=20220830_143151189_255.mdj, downloadCount=0, createdAt=null), Attachment(no=0, boardNo=0, originalFilename=2022-03-03.png, renamedFilename=20220830_143151198_923.png, downloadCount=0, createdAt=null)])

서버 컴퓨터에 잘 저장된 것을 확인할 수 있습니다.


DB 저장


Controller

BoardController

@PostMapping("/boardEnroll.do")
public String boardEnroll(Board board, @RequestParam(name = "upFile") List<MultipartFile> upFileList, RedirectAttributes redirectAttr) throws IllegalStateException, IOException {
    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());

        // 파일이 없어도 빈 객체가 넘어오므로 분기처리!
        if(!upFile.isEmpty()) {				
            // a. 서버컴퓨터 저장
            String saveDirectory = application.getRealPath("/resources/upload/board");
            String renamedFilename = HelloSpringUtils.getRenamedFilename(upFile.getOriginalFilename()); // 20220830_141822222_123.txt
            File destFile = new File(saveDirectory, renamedFilename); // 해당 경로에 해당 이름을 가진 파일객체
            upFile.transferTo(destFile); // 해당 경로에 파일을 저장

            // b. DB저장을 위해 Attachment객체 생성
            Attachment attachment = new Attachment(upFile.getOriginalFilename(), renamedFilename);
            board.add(attachment);
        }
    }

    log.debug("board = {}", board);

    int result = boardService.insertBoard(board);
    redirectAttr.addFlashAttribute("msg", "게시글을 성공적으로 등록했습니다.");

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

 

Service

BoardService interface 생략

BoardServiceImpl

@Override
public int insertBoard(Board board) {
    // insert board
    int result = boardDao.insertBoard(board);

    // insert Attachment
    List<Attachment> attachments = board.getAttachments();
    if(!attachments.isEmpty()) {
        for(Attachment attach : attachments) {
            attach.setBoardNo(board.getNo());
            result = boardDao.insertAttachment(attach);
        }
    }
    return result;
}

 

Dao

BoardDao interface

@Insert("insert into board values(seq_board_no.nextval, #{title}, #{memberId}, #{content}, default, default, default")
@SelectKey(statement = "select seq_board_no.currval from dual", before = false, keyProperty = "no", resultType = int.class)
int insertBoard(Board board);

@Insert("insert into attachment values(seq_attahcment_no.nextval, #{boardNo}, #{originalFilename}, #{renamedFilename}, default, default")
int insertAttachment(Attachment attach);

attachment 테이블에 방금 저장된 board_no 컬럼이 필요하기 때문에 @SelectKey를 이용하여 해당 값을 가져와 처리해주었습니다.

statement = "select seq_board_no.currval from dual"를  @Insert 처리 후에(before = false), int 형으로 변환하여(resultType = int.class) Board의 setNo (KeyProperty = "no") 해주세요. 를 의미합니다.

따라서 Board 객체에 no 컬럼이 방금 저장된 no컬럼으로 지정되어있으므로 해당 값을 이용하여 attachment 테이블의 board_no 컬럼을 처리하였습니다.

 

board 테이블
attachment 테이블

 

서버 컴퓨터 및 db에 성공적으로 저장된 것을 확인할 수 있으며, attachment 테이블의 board_no 또한 잘 연결되어있습니다.