Spring-MyWeb 파일 업로드

정원·2022년 6월 25일

Spring-MyWeb

목록 보기
12/16

22.06.24 이미지 파일 업로드하는 방법을 알아보기, UUID

SNS 게시판 추가

브라우저 화면보기 위해서 간단히 controller구성

header.jsp 메뉴 추가

<li class="active"><a href="<c:url value='/' />">Main</a></li>
<li><a href="<c:url value='/freeboard/freeList' />">자유게시판</a></li>
<li><a href="<c:url value='/snsBoard/snsList' />">SNS</a></li>

SnsBoardController

package com.spring.myweb.controller;
@Controller
@RequestMapping("/snsBoard")
public class SnsBoardController {
	
	@GetMapping("/snsList")
	public void snsList() {}
}

이미지 업로드

라이브러리 추가

1.Maven Repository - Apache Commons FileUpload
2.Maven Repository - Apache Commons IO » 2.4

pom.xml 설정 추가

<!-- 서블릿 3.0 이상 사용 가능한 파일 업로드 API -->
<dependency>
	<groupId>commons-fileupload</groupId>
	<artifactId>commons-fileupload</artifactId>
	<version>1.3.1</version>
</dependency>

<!-- commons-io -->
<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.4</version>
</dependency>

servlet-config.xml

<!-- 파일 업로드 -->
<!-- 반드시 id를  "multipartResolver"로 선언
	Multipart 형식으로 전달되는 데이터를 스프링 mvc에서 사용할 수 있도록 변환해 주는 객체-->
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">		
	<!-- 최대 업로드 가능한 바이트 크기(바이트 단위), value에 -1을 주면 제한이 없음을 의미 -->
	<beans:property name="maxUploadSize" value="1048576"/> <!-- 1메가바이트 -->
		
	<!-- 업로드 요청을 변환할 때 사용할 문자 인코딩 방식 -->
	<beans:property name="defaultEncoding" value="utf-8" />
</beans:bean>

파일 한 개 업로드 방법

upload.jsp

연습용 jsp파일 생성.
파일 업로드에서는 enctype(인코딩타입)을 "multipart/form-data"로 반드시 지정해야 한다.

<body>	
	<form action="upload_ok" method="post" enctype="multipart/form-data">
		파일 선택: <input type="file" name="file"> <br>
		<input type="submit" value="전송">
	</form>	
</body>

UploadController

연습용 컨트롤러 생성.
upload.jsp에서 사용자가 file을 선택후 controller로 보내진다.
MultipartFile 인터페이스 타입으로 file을 받는다.
UUID는 파일의 고유 번호로, 파일명 중복 방지를 위해 적용한다.

<script>
package com.spring.myweb.controller;

@Controller
@RequestMapping("/fileupload")
public class UploadController {
	
    //업로드 화면요청
	@GetMapping("/upload")
	public void form() {}
	
    //업로드 요청
	@PostMapping("/upload_ok") //변수명 같으면 @RequestParam안써도 된다.
	public String upload(@RequestParam("file") MultipartFile file) { //MultipartFile 인터페이스 타입
		
		//실제 파일 저장 메서드(fileWriter 작업을 손쉽게 한방에 처리해 준다.)
		try {
			String fileRealName = file.getOriginalFilename(); //파일 원본명
			long size = file.getSize(); //파일 크기
			System.out.println("파일명: " + fileRealName);
			System.out.println("사이즈: " + size);
			
			//DB에는 파일 경로를 저장, 실제 파일은 서버 컴퓨터의 로컬 경로에 저장하는 방식.
			String uploadFolder = "C:\\test\\upload"; //폴더 경로
			String fileExtension = fileRealName.substring(fileRealName.lastIndexOf("."), fileRealName.length()); //확장자 얻기
			/*
		        파일 업로드 시 파일명이 동일한 파일이 이미 존재할 수도 있고,
		        사용자가 업로드하는 파일명이 영어 이외의 언어로 되어있을 수 있습니다.
		        타 언어를 지원하지 않는 환경에서는 정상 동작이 되지 않습니다. (리눅스)
		        고유한 랜덤 문자를 통해 DB와 서버에 저장할 파일명을 새롭게 만들어 줍니다.
	        */
			UUID uuid = UUID.randomUUID(); //문자들이 - 으로 연결되어 있다.
			System.out.println(uuid.toString()); //f99564fd-e7af-47a8-8f64-53d3d7496c3a
			String[] uuids = uuid.toString().split("-"); //String[]로 리턴
			System.out.println("생성된 고유 문자열: " + uuids[0]); //분할한 것중 한덩어리만 사용해도 충분.f99564fd
			System.out.println("확장자명: " + fileExtension); //.png
			
			//자바 객체(File) 활용해서 폴더 생성
			File folder = new File(uploadFolder); //폴더 경로를 매개값으로 전달
			if(!folder.exists()) { //폴더가 존재하는지 확인.
				folder.mkdirs(); //폴더가 존재하지 않는다면 생성해라.
			}
			
			folder = new File(uploadFolder + "\\" + uuids[0] + fileExtension);
			//새로운 파일 생성.폴더경로+파일명+확장자명
			file.transferTo(folder); //파일 업로드.예외발생 try/catch
		} catch (Exception e) {
			e.printStackTrace();
		} 	
		
		return "fileupload/upload_ok";
	}
}
</script>

이렇게 메서드가 실행되고 나면
실제 C:\test\upload경로에 폴더가 생성되고
생성한 파일명으로 파일이 경로에 저장된다.

여러개 파일 전송 방법 1

MultipartHttpServletRequest 인터페이스 타입사용

upload.jsp

input태그 속성에 multiple="multiple" 추가하면
사용자가 파일 여러개를 선택할 수 있다.

<form action="upload_ok2" mehtod="post" enctype="multipart/form-data">
	파일 선택: <input type="file" multiple="multiple" name="files">
	<input type="submit" value="전송">
</form>

UploadController

"C:/test/upload" == "C:\test\upload" 정슬레시,백슬레시 둘다 사용가능.

<script>
@PostMapping("/upload_ok2")
public String upload2(MultipartHttpServletRequest files) { //MultipartHttpServletRequest 인터페이스 타입 사용
		
	//서버에서 저장할 파일 경로
	String uploadFolder = "C:/test/upload";
		
	List<MultipartFile> list = files.getFiles("files");
		
	/* 일반 for문 사용
	for(int i=0; i<list.size(); i++) {
		try {
			String fileRealName = list.get(i).getOriginalFilename();
			long size = list.get(i).getSize();
			
			System.out.println("파일명: " + fileRealName);
			System.out.println("사이즈: " + size);
				
			File saveFile = new File(uploadFolder + "/" + fileRealName);
			list.get(i).transferTo(saveFile);
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}*/
	
    //향상 for문 사용
	for(MultipartFile m : list) {					
		try {
			String fileRealName = m.getOriginalFilename();
			long size = m.getSize();
			System.out.println("파일명: " + fileRealName);
			System.out.println("사이즈: " + size);
				
			File saveFile = new File(uploadFolder+ "/" + fileRealName);
			m.transferTo(saveFile);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}		
	return "fileupload/upload_ok";
}
</script>

여러개 파일 전송 방법 2

List<MultipartFile> List타입으로 받기.

upload.jsp

multiple="multiple" 속성 추가 하지 않고 하나씩
파일을 선택하게 해서 모든 파일들을 List로 받는다.
만약 input 태그가 3개인데 1개만보낸다면 에러가 발생하기 때문에
프론트 단에서 확인하거나 null이 들어온다면 실행하는 로직을 추가 해야한다.

<form action="upload_ok3" method="post" enctype="multipart/form-data">
	파일 선택: <input type="file" name="file"> <br>
	파일 선택: <input type="file" name="file"> <br>
	파일 선택: <input type="file" name="file"> <br>
	<input type="submit" value="전송">
</form>

UploadController

<script>
@PostMapping("/upload_ok3")
public String upload3(@RequestParam("file") List<MultipartFile> list) {
		
	String uploadFolder = "C:/test/upload";
	
	for(MultipartFile m : list) {	
		try {
			String fileRealName = m.getOriginalFilename();
			long size = m.getSize();
			System.out.println("파일명: " + fileRealName);
			System.out.println("사이즈: " + size);

			File saveFile = new File(uploadFolder+ "/" + fileRealName);
			m.transferTo(saveFile);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	return "fileupload/upload_ok";
}
</script>

다른예제

커맨드 객체 사용

upload.jsp

사용자에게 직접 파일명과 파일을 받는다.

<form action="upload_ok4" method="post" enctype="multipart/form-data">
	원하시는 파일명: <input type="text" name="name">
	파일 선택: <input type="file" name="file"> <br>		
	<input type="submit" value="전송">
</form>

UploadVO

사용자가 입력한 파일명과 파일을 저장할 수 있는 UploadVO생성

public class UploadVO {
	private String name;
	private MultipartFile file;
}

UploadController

컨트롤러에서는 VO객체로 처리.

@PostMapping("/upload_ok4")
public String upload4(UploadVO vo) {
	...
}

MultiUploadVO

만약 사용자가 1개의 파일이 아니라 여러개의 파일을 업로드할때
커맨드 객체 사용하려면 여러파일을 받을수있는 MultiUploadVO 객체를 생성해서 이용한다.

public class MultiUploadVO {	
	private List<UploadVO> list;
}

upload.jsp

list의 인덱스를 이용해서 값들을 저장.

<form action="upload_ok4" method="post" enctype="multipart/form-data">
	원하시는 파일명: <input type="text" name="list[0].name">
	파일 선택: <input type="file" name="list[0].file"> <br>
		
	원하시는 파일명: <input type="text" name="list[1].name">
	파일 선택: <input type="file" name="list[1].file"> <br>
		
	원하시는 파일명: <input type="text" name="list[2].name">
	파일 선택: <input type="file" name="list[2].file"> <br>		
	<input type="submit" value="전송">
</form>

UploadController

vo에서 getList( )를 해서 list를 받고 반복문을 이용한다.
uvo.getName( )을 해서 사용자가 입력한 파일명을 받아오고
확장자명을 위해서 uvo.getFile().getOriginalFilename()도 진행.

<script>
@PostMapping("/upload_ok4")
public String upload4(MultiUploadVO vo) {
		
	System.out.println(vo);
		
	String uploadFolder = "C:/test/upload";
	List<UploadVO> list = vo.getList();
		
	for(UploadVO uvo : list) {
		try {
			String fileName = uvo.getName();
			String realName = uvo.getFile().getOriginalFilename();
			String fileExtention = realName.substring(realName.lastIndexOf("."), realName.length());				
				
			File saveFile = new File(uploadFolder+ "/" + fileName + fileExtention);
			uvo.getFile().transferTo(saveFile);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	return "fileupload/upload_ok";
}
</script>

0개의 댓글