Spring 이미지(파일) 업로드

주빈·2022년 8월 11일
0

framework

목록 보기
11/11
post-thumbnail

프로젝트 당시에 이미지 경로 및 업로드에 문제가 있어서 저장 폴더에 이미지가 어떤 경우엔 올라가고 어떤 경우엔 올라가지 않아서 오늘 다시 한번 복습해보도록 하자...

📘 기본 세팅

일단 Spring 프로젝트에서 기본 설정을 해줘야 한다.

📜 pom.xml에서 dependency를 추가한다.

<!-- 파일 업로드 라이브러리 -->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

📜 root-context.xml에서 bean 등록을 한다.

<!-- 파일 업로드를 위한 MutipartResolver 구현체 CommonsMultipartResolver  bean 등록 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <property name="maxUploadSize" value="104857600"/>
  <property name="maxUploadSizePerFile" value="104857600"/>
  <property name="maxInMemorySize" value="104857600"/>
</bean>

<property> 부분의 프로퍼티를 이용하여 최대 가능한 업로드 사이즈 등 여러가지를 지정할 수 있다.

📜 JSP에 form태그 수정

JSP에서 <form>태그를 이용하여 이미지를 등록할 때
파일처리를 위해서 form 태그 내에 enctype 및 전송 방식을 설정한다.

enctype 속성을 "multipart/form-data"로 설정
method 속성을 "post"로 설정

<form action="${contextPath}/board/itemUpload" method="post" enctype="multipart/form-data">
...
</form>

✏ 게시글 작성으로 예시보기

프로젝트 당시 판매글을 올릴 때 사진도 같이 올리는 방식으로 하였다.
이 때의 코드를 보면서 복습해보자.

Controller

@PostMapping("board/itemUpload")
public String boardWrite(@ModelAttribute("loginMember") Member loginMember,
						 @RequestParam(value = "images", required = false) List<MultipartFile> imageList,
                         ItemBoard item,
                         HttpServletRequest req) throws IOException {
	
    String webPath = "resources/images/items/";
    String folderPath = req.getSession().getServletContext().getRealPath(webPath);
    
	int boardNo = service.insertBoard(item, imageList, webPath, folderPath);
    
 	String path = null;
    
    if (boardNo > 0) { // 등록 성공 시
    	path = "../board/detail/" + boardNo;
    } else { // 등록 실패 시
    	path = req.getHeader("referer");
    }
    
    return "redirect:" + path;
}
  • @ModelAttribute로 로그인 중인 회원 정보를 얻는다. (회원 번호가 필요)
  • JSP에서 이미지를 여러 개 등록할 수 있는데 이를 List<MultipartFile>로 받아온다.
  • 게시글 제목, 내용 등 등록 시 필요한 정보 item을 받아온다.
  • 이미지 업로드 시에 예외가 발생할 수 있으므로 throws IOException을 작성한다.
  • 웹 상에서 접근 가능한 경로인 webPath를 설정해준다.
String webPath = "/resources/images/items/";
  • 실제로 서버에 저장될 folderPath를 설정해준다.
// webPath 값을 지정하면 해당경로까지의 realPath를 추출하는 코드
String folderPath = req.getSession().getServletContext().getRealPath(webPath); 

Controller에서 service를 호출하여 작성하는 부분을 살펴보자.

Service

@Override
public int insertBoard(ItemBoard item, List<MultipartFile> imageList, String webPath, String folderPath,
	) throws IOException {

	// XSS 방지를 위한 Util에서 만들어둔 메서드 처리하기
    item.setBoardTitle(Util.XSSHandling(item.getBoardTitle()));
	item.setBoardContent(Util.XSSHandling(item.getBoardContent()));

	// 이미지 저장 테이블이 따로 있기 때문에 boardNo를 일단 먼저 구한다.
	int boardNo = dao.insertBoard(item);

	if (boardNo > 0) { // 이미지를 제외한 게시글 삽입 성공 시
    
		List<BoardImage> boardImageList = new ArrayList<BoardImage>();
		List<String> reNameList = new ArrayList<String>();

		for (int i = 0; i < imageList.size(); i++) {

			if (imageList.get(i).getSize() > 0) { // i번째 요소에 업로드된 이미지가 있을 경우

				// 이미지 이름 변경 (날짜 및 시간으로)
				String reName = Util.fileRename(imageList.get(i).getOriginalFilename());
				reNameList.add(reName);

				BoardImage img = new BoardImage();
				img.setBoardNo(boardNo);
				img.setImageLevel(i);
				img.setImageOriginal(imageList.get(i).getOriginalFilename());
				img.setImageReName(webPath + reName);

				boardImageList.add(img);
			}
		}
        
		// 분류 작업 종료 후 boardIamgeList가 비어있지 않은 경우 == 파일이 업로드가 된 경우
		if (!boardImageList.isEmpty()) {
        
        	// 이미지 분류 작언이 된 것들을 DB에 저장
			int result = dao.insertBoardImageList(boardImageList);

			// result == 삽입 성공한 행의 갯수, 단지 0,1이 아니다.

			if (result == boardImageList.size()) { // 삽입된 행의 갯수과 업로드 이미지 수가 같을 경우

				// 이제야 서버에 이미지를 저장한다.
				for (int i = 0; i < boardImageList.size(); i++) {

					int index = boardImageList.get(i).getImageLevel();
					imageList.get(index).transferTo(new File(folderPath + reNameList.get(i)));
				}
			} 
		}
	}

	return boardNo;
}
  • imageList에는 multipartFile로 된 실제로 삽입된 이미지가 존재한다.
    그것을 파일로 변화해서 업로드를 하는 것이다.

    1. 우선 이미지 리스트에 파일을 저장한다. 파일이 비어있더라도 받아온다.
    2. 이것을 파일이 존재하는 것만 boardImageList에 저장한다. 이 때, 경로 webPath가 붙어서 이 동한다.
    3. reNameList는 바뀐 이름을 저장한다.

DAO쪽은 단순 insert 처리해주는 부분이므로 생략하도록하자.


앞으론 이미지 경로를 잘못 설정하여 프로젝트 실행 시 이미지가 깨지는 경우는 절대 없도록하자..^^

profile
누구에게나 필요한 개발자가 꿈

0개의 댓글