프로그래밍/Spring & Spring boot

[Spring/스프링] 파일 업로드 (single file , multi file )

pupu91 2022. 9. 11. 18:19
반응형

파일 업로드를 위한 환경설정

 


1) 파일 업로드  commoms-io , commons-fileupload 라이브러리 추가 

    pom.xml 에 추가(파일 업로드 관련 의존성이 추가되야 라이브러리 사용가능)

 

 

 

2) servlet-context.xml에 CommonsMultipartResolver  bean등록

위의 라이브러리를 활용하려면 파일이 전송되었을때 알맞게 가공처리해줄 수 있는 기능을 가진 빈을 등록

라이브러리와 빈등록을 하면 가공된 형태의 객체로 넘겨줄수있음(매개변수에 전달)

 

 

 

 

3) multipart로 전송 된 요청에 대한 인코딩 처리

일반 인코딩 필터로 구현하기 어려우므로 스프링에서 제공하는 인코딩 필터 (CharacterEncodingFilter)를 web.xml 에 설정

 encoding filter 추가
 CharacterEncodingFilter : 정의 되어 있는 파일 인코딩 필터
	
 1. 필터 등록하기
<filter>
	<filter-name> encodingFilter </filter-name>
	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
	<init-param> <!-- 필터의 init 메소드 쪽으로 전달해줄 초기화 파라미터 설정-->
		<param-name>encoding</param-name>
		<param-value>UTF-8</param-value>
	</init-param>
</filter>
	
2. 필터 매핑하기
<filter-mapping> 등록된 필터를 어떤 요청과 매핑할것인가?
	<filter-name>encodingFilter</filter-name> <!-- 위에서 등록한 필터명칭을 이용해서 설정해야함.-->
	<url-pattern>/*</url-pattern> <!-- 모든 요청에 대해서  CharacterEncodingFilter를 동작시킬것이고 그때의 설정은 utf-8이다.-->
</filter-mapping>

 

 

 

4) properies 파일에 upload 경로 설정하기

 

 

 


jsp 파일 생성

 


 

 

1. main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	
	<h1 align="center">파일 업로드 하기</h1>
	
	<h3>single file 업로드 하기</h3>
	<form action="single-file" method="post" encType="multipart/form-data"><!-- 인코딩 타입 설정 꼭해주깅 -->
		파일 : <input type="file" name="singleFile"><br>
		파일 설명 : <input type="text" name="singleFileDescription"><br>
		<input type="submit">		
	</form>
	
	<h3>multi file 업로드 하기 </h3>
	<form action="multi-file" method="post" encType="multipart/form-data">
		파일 : <input type="file" name="multiFiles" multiple><br>
		파일 설명 : <input type="text" name="multiFileDescription"><br>
		<input type="submit">		
	</form>	
</body>
</html>

 

 

2. message page.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1 align="center">${ requestScope.message }</h1>
</body>
</html>
반응형

 


single file 업로드 

 


@Controller
@PropertySource("classpath:config/common.properties")
public class FileUploadController {
	
    @Value("${file.path}") //프로퍼티 파일에 작성한 키값 
    private String filePath; //필드 값에 file.path 경로 들어감
    
    @PostMapping("/single-file")
    public String singleFileupload(@RequestParam MultipartFile singleFile,
    					@RequestParam String singleFileDescription, Model model) {
        
                 //파라미터로 넘긴 값이 잘 넘어오는지 확인을 위한 출력문
                 System.out.println("singleFile : " + singleFile); 
       
                //첨부파일이름출력
		System.out.println("singleFile.getOriginalFilename() :" + singleFile.getOriginalFilename());
        
               //파일설명출력
		System.out.println("singFileDescription : " + singleFileDescription);
		System.out.println("filePath : " + filePath);
		
		//파일을 저장할 경로가 있는지 확인하여 없으면 생성하는 구문 
		File mkdir = new File(filePath); // 경로에 대한 파일객체 생성
		if(!mkdir.exists()) mkdir.mkdirs();
                => exists()해당 경로가 물리적으로 존재하는지 확인하는 메소드
                   mkdirs()하위경로를 여러개 만들 수 있는 메소드
                   경로가 진짜로 있나? 경로가 없으면 mkdirs를 이용해서 만들어라

		//파일명을 고유한 값으로 변경하는 처리
		String originalFileName = singleFile.getOriginalFilename();
		
        String ext = originalFileName.substring(originalFileName.lastIndexOf(".")); 
        => 뒤에서부터 .이 가장 마지막에있는 문자열의 인덱스를 찾고, substring으로 인덱스 위치부터 끝까지 잘라서 저장 (확장자만 잘라서 저장)
		
        String savedName = UUID.randomUUID().toString() + ext; 
        => uuid 클래스 : 고유한 아이디 값을 만들어 줄 수 있는 클래스 
           랜덤한 아이디를 만들어 달라-> 만들어진 아이디를 문자열로 처리한 다음 확장자 붙여서 저장
		System.out.println("savedName : " + savedName);
		
		//파일을 저장
		try {
        	transferTo 에 원하는 파일 또는 경로를 전달하면 그 경로에 파일을 만들어 줌
			singleFile.transferTo(new File(filePath + "/" + savedName));
			model.addAttribute("message", "파일 업로드 성공!");
		} catch (IllegalStateException | IOException e) {
			model.addAttribute("message", "파일 업로드 실패!");
		} //경로에 전송해줌
		
		return"result";
	}	
}

 

 

 

화면 결과

- main 페이지

 

 

 

 

 

- 업로드 성공 화면

 

 

- 정상적으로 업로드 되면 properties파일에 작성해놓은 경로에 맞춰 폴더 생성되고 그 하위에 사진 저장됨.

 

 

 

 

 

 


multi file 업로드

 


 

@Controller
@PropertySource("classpath:config/common.properties") //
public class FileUploadController {
	
	@Value("${file.path}")
	private String filePath;

    @PostMapping("multi-file")     
	public String multiFileUpload(@RequestParam List<MultipartFile> multiFiles, 
			@RequestParam String multiFileDescription, Model model) {
		
		System.out.println("multiFiles : " + multiFiles);
		System.out.println("multiFileDescription : " + multiFileDescription);
		
		//파일 경로 있는지 확인하고 없으면 생성
		File mkdir = new File(filePath);
		if(!mkdir.exists()) mkdir.mkdirs();
		
		//파일과 관련 된 정보를 추출하여 보관하고 추후에는 DB에 insert할 때 전달
		List<Map<String, String>> files = new ArrayList<>();
		
		for(MultipartFile file : multiFiles) {
			
			//파일명 변경 처리 
			String originalFileName = file.getOriginalFilename();
			String ext = originalFileName.substring(originalFileName.lastIndexOf("."));
			String savedName = UUID.randomUUID().toString() + ext;
			
			//1개의 파일에 관한 정보 Map에 보관
			Map<String, String> fileInfo = new HashMap<>();
			fileInfo.put("originalFileName", originalFileName); //원래이름
			fileInfo.put("savedName", savedName);//지금 저장된 이름(고유아이디)
			fileInfo.put("filePath", filePath); //경로
			
			//여러 개의 파일 정보 보관하는 List에 Map 추가 
			files.add(fileInfo);
		}
		
		
		try {
			//파일 저장 하기
			for (int i = 0; i < multiFiles.size(); i++) {
				multiFiles.get(i).transferTo(new File(filePath + "/" + files.get(i).get("savedName")));
			} 	
            
                    → multiFiles 사이즈 만큼 반복하겠다. get인덱스를 통해서 값을 꺼내서 transferTo를 이용하여 저장하는데,
                    고정된 파일 경로에다가 files에 키값이 savedName 인 값을 저장해라 
			
			model.addAttribute("message", "파일 업로드 성공!");
			
		} catch (IllegalStateException | IOException e) {
			 //업로드 실패 시 이전에 저장된 파일도 삭제
			for (int i = 0; i < multiFiles.size(); i++) {
				new File(filePath + "/" + files.get(i).get("savedName")).delete(); 
                파일객체를 만들고 지워주세요
			}
			
			model.addAttribute("message", "파일 업로드 실패!");
		}
		
		return "result";
	}
	
}
반응형