Spring Boot

230221 Spring Boot 파일 업로드 방식

주영재 2023. 2. 21. 19:08

ex01,ex01_ok.html, UploadController.java

더보기

ex01.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h3>업로드 예제</h3>
	
	<!-- 단일파일 업로드 -->
	<form action="upload_ok" method="post" enctype="multipart/form-data">
		<input type="file" name="file"/><br/>
		<input type="submit" value="업로드"/><br/>
	</form>
	
	<hr/>
	
	<!-- 다중파일 업로드 -->
	<form action="upload_ok2" method="post" enctype="multipart/form-data">
		<input type="file" name="file" multiple="multiple"/><br/>
		<input type="submit" value="업로드"/><br/>
	</form>
	
	
	<hr/>
	<h3>복수태그로 여러파일 업로드</h3>
	<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="업로드"/><br/>
	</form>
	
	<hr/>
	<h3>비동기형식의 업로드</h3>
	<div>
		<input type="file" name="file" id="a"/><br/>
		<input type="text" name="writer" id="writer"/>
		<input type="button" value="업로드" id="btn"/><br/>
	</div>
	
	<script src="https://code.jquery.com/jquery-3.6.3.js"></script>
	<script>
		$("#btn").click(()=>{
			//파일데이터 추출
			var file=$("#a");
			console.log(file[0]);//순수한 태그
			console.dir(file[0].files[0]); //파일데이터
			
			//사용자가 입력 text
			var writer=$("#writer").val();
			
			//폼태그로 추가
			var formData = new FormData(); //폼객체
			formData.append("file",file[0].files[0]); //name, 값
			formData.append("writer",writer); //name,값
			
			$.ajax({
				url:"upload_ok4",
				type:"post",
				data:formData, //보내는데이터 form
				contentType:false, //보내는데이터타입 false->"multipart/form-data"로 선언됩니다.
				processData:false, //폼데이터가 name=값&name=값 형식으로 자동변경되는 것을 막아줍니다.
				success:(result)=>{ //콜백
					if(result=="success"){
						alert("업로드가 완료되었습니다.");
					}
				},
				error:(err)=>{
					alert("업로드 에러발생");
				}
			})
		})
	</script>
</body>
</html>

 

 

 

ex01_ok.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<h3>결과페이지</h3>
	<a href="ex01">다시올리기</a>
	
</body>
</html>

 

 

 

UploadController.java

package com.simple.basic.controller;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import net.coobird.thumbnailator.Thumbnailator;

@Controller
@RequestMapping("/upload")
public class UploadController {

	@GetMapping("/ex01")
	public void ex01() {}

	@Value("${project.uploadpath}")
	private String uploadpath;


	//날짜별로 폴더생성
	public String makeDir() {

		Date date=new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
		String now=sdf.format(date);

		String path=uploadpath + "\\" +now; //경로
		File file = new File(path);

		if(file.exists()==false) {//파일이 존재하면 true
			file.mkdir(); //폴더생성
		}

		return path;
	}



	//단일파일업로드
	@PostMapping("/upload_ok")
	public String uploadOk(@RequestParam("file") MultipartFile file) {

		//		String origin=file.getOriginalFilename();//파일명
		//		long size=file.getSize();//사이즈
		//		String type=file.getContentType();//파일데이터의 컨텐츠타입
		//		try {
		//			byte[] arr=file.getBytes();
		//			System.out.println(arr);
		//		} catch (IOException e) {
		//			e.printStackTrace();
		//		}

		String origin = file.getOriginalFilename(); //파일명
		String filename=origin.substring(origin.lastIndexOf("\\")+1); //브라우저별로 경로가 포함되서 올라오는 경우가 있기에 간단한 처리.

		//폴더생성
		String filepath=makeDir();

		//중복파일의 처리
		String uuid=UUID.randomUUID().toString();
		//최종저장경로
		String savename=filepath+"\\"+uuid+"_"+filename;



		//System.out.println(origin);
		System.out.println(filename);
		System.out.println(filepath);
		System.out.println(uuid);
		System.out.println(savename);


		try {
			File save = new File(savename); //세이브경로
			file.transferTo(save);//업로드 진행
			
			//썸네일경로
			String thumbsname= filepath+"\\"+uuid+"_thumbs_"+filename;
			
			//썸네일 생성 (복사할파일위치,썸네일생성경로,가로,세로)
			Thumbnailator.createThumbnail(new File(savename),new File(thumbsname),150, 150);
			
		} catch (Exception e) {
			e.printStackTrace();
		}

		return "upload/ex01_ok";
	}
/////////////////////////////////////////////////////////////////////////
	//multiple옵션으로 다중파일 업로드
	@PostMapping("/upload_ok2")
	public String uploadOk2(MultipartHttpServletRequest files ) {

		//name태그가 file인 것을 찾음
		List<MultipartFile> list=files.getFiles("file");

		for(MultipartFile file : list) {
			//파일명
			String origin = file.getOriginalFilename(); 
			//브라우저별로 경로가 포함되서 올라오는 경우가 있기에 간단한 처리.
			String filename=origin.substring(origin.lastIndexOf("\\")+1); 
			//폴더생성
			String filepath=makeDir();
			//중복파일의 처리
			String uuid=UUID.randomUUID().toString();
			//최종저장경로
			String savename=filepath+"\\"+uuid+"_"+filename;
			try {
				File save = new File(savename); //세이브경로
				file.transferTo(save);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return "upload/ex01_ok";
	}
/////////////////////////////////////////////////////////////////////////

	//복수태그로 여러파일 업로드
	@PostMapping("/upload_ok3")
	public String uploadOk3(@RequestParam("file") List<MultipartFile> list) {
		
		//리스트에서 빈값은 제거
		list=list.stream().filter((x)->x.isEmpty()==false ).collect(Collectors.toList());
		
		for(MultipartFile file:list) {
			//파일명
			String origin = file.getOriginalFilename(); 
			//브라우저별로 경로가 포함되서 올라오는 경우가 있기에 간단한 처리.
			String filename=origin.substring(origin.lastIndexOf("\\")+1); 
			//폴더생성
			String filepath=makeDir();
			//중복파일의 처리
			String uuid=UUID.randomUUID().toString();
			//최종저장경로
			String savename=filepath+"\\"+uuid+"_"+filename;
			try {
				File save = new File(savename); //세이브경로
				file.transferTo(save);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		return "upload/ex01_ok";
	}
/////////////////////////////////////////////////////////////////////////
	//비동기 파일 업로드 -넘어오는 데이터는 form형식이기 때문에 vo or requestParam으로 받으면 된다.
	@PostMapping("/upload_ok4")
	@ResponseBody //Response가 붙으면 return의 값이 요청이 온곳으로 반환
	public String uploadOk4(@RequestParam("file")MultipartFile file, @RequestParam("writer")String writer) {
		//System.out.println(file);
		//System.out.println(writer);
		//파일명
		String origin = file.getOriginalFilename(); 
		//브라우저별로 경로가 포함되서 올라오는 경우가 있기에 간단한 처리.
		String filename=origin.substring(origin.lastIndexOf("\\")+1); 
		//폴더생성
		String filepath=makeDir();
		//중복파일의 처리
		String uuid=UUID.randomUUID().toString();
		//최종저장경로
		String savename=filepath+"\\"+uuid+"_"+filename;
		try {
			File save = new File(savename); //세이브경로
			file.transferTo(save);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return "success";
	}
	
}

 


단일파일 업로드

html

<!-- 단일파일 업로드 -->
<form action="upload_ok" method="post" enctype="multipart/form-data">
	<input type="file" name="file"/><br/>
	<input type="submit" value="업로드"/><br/>
</form>

 

 

Controller

@Controller
@RequestMapping("/upload")
public class UploadController {

	@GetMapping("/ex01")
	public void ex01() {}

	@Value("${project.uploadpath}")
	private String uploadpath;


	//날짜별로 폴더생성
	public String makeDir() {

		Date date=new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
		String now=sdf.format(date);

		String path=uploadpath + "\\" +now; //경로
		File file = new File(path);

		if(file.exists()==false) {//파일이 존재하면 true
			file.mkdir(); //폴더생성
		}

		return path;
	}
    
    @PostMapping("/upload_ok")
	public String uploadOk(@RequestParam("file") MultipartFile file) {

		//String origin=file.getOriginalFilename();//파일명
		//long size=file.getSize();//사이즈
		//String type=file.getContentType();//파일데이터의 컨텐츠타입
		//try {
		//	byte[] arr=file.getBytes();
		//	System.out.println(arr);
		//} catch (IOException e) {
		//	e.printStackTrace();
		//}

		String origin = file.getOriginalFilename(); //파일명
		String filename=origin.substring(origin.lastIndexOf("\\")+1); //브라우저별로 경로가 포함되서 올라오는 경우가 있기에 간단한 처리.

		//폴더생성
		String filepath=makeDir();

		//중복파일의 처리
		String uuid=UUID.randomUUID().toString();
		//최종저장경로
		String savename=filepath+"\\"+uuid+"_"+filename;



		//System.out.println(origin);
		System.out.println(filename);
		System.out.println(filepath);
		System.out.println(uuid);
		System.out.println(savename);

		File save = new File(savename); //세이브경로

		try {
			file.transferTo(save);//업로드 진행
		} catch (Exception e) {
			e.printStackTrace();
		}

		return "upload/ex01_ok";
	}

String originName =file.getOriginalFilename();
->
IE, Edge는 전체경로가 들어오므로 \\기준으로 파일명만 추출
String filename=originName.substring(originName.lastIndexOf("\\")+1);

mkdir(make directory)

중복파일 처리 필요
같은 파일을 올리면 덮어씌워버린다.->UUID사용.

 

form의 데이터를 @RequestParam("file속성 input태그 name") MultipartFile file로 받는다.

 

파일을 선택하면 파일업로드창이 뜨고, 업로드 버튼을 누르면 지정한 upload폴더에 생성된 폴더 내에 파일이 저장된다.

 

폴더와 이름까지 지정됨. 페이지는 성공하면 ok페이지로 넘어간다.


다중파일 업로드

<input type="file" />태그의 multiple옵션
파일을 여러개 선택하는 것이 가능


컨트롤러에서 MultipartHttpServletRequest로 받는다.
->MultipartHttpServletRequest files
files.getFiles("input태그 name")를 하면 list<MultipartFile>로 반환한다.
for문으로 반복. for문 안 구문은 단일파일 업로드 구문과 완전 동일.

 

 

 

html

<!-- 다중파일 업로드 -->
<form action="upload_ok2" method="post" enctype="multipart/form-data">
	<input type="file" name="file" multiple="multiple"/><br/>
	<input type="submit" value="업로드"/><br/>
</form>

multiple="multiple"속성을 부여

->파일 업로드 창이 뜰 때 한번에 여러 파일을 올리는 것이 가능해진다.

 

 

 

Controller

@Value("${project.uploadpath}")
private String uploadpath;

//날짜별로 폴더생성
public String makeDir() {
	Date date=new Date();
	SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
	String now=sdf.format(date);

	String path=uploadpath + "\\" +now; //경로
	File file = new File(path);

	if(file.exists()==false) {//파일이 존재하면 true
		file.mkdir(); //폴더생성
	}

	return path;
}

//multiple옵션으로 다중파일 업로드
	@PostMapping("/upload_ok2")
	public String uploadOk2(MultipartHttpServletRequest files ) {

		//name태그가 file인 것을 찾음
		List<MultipartFile> list=files.getFiles("file");

		for(MultipartFile file : list) {
			//파일명
			String origin = file.getOriginalFilename(); 
			//브라우저별로 경로가 포함되서 올라오는 경우가 있기에 간단한 처리.
			String filename=origin.substring(origin.lastIndexOf("\\")+1); 
			//폴더생성
			String filepath=makeDir();
			//중복파일의 처리
			String uuid=UUID.randomUUID().toString();
			//최종저장경로
			String savename=filepath+"\\"+uuid+"_"+filename;
			try {
				File save = new File(savename); //세이브경로
				file.transferTo(save);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return "upload/ex01_ok";
	}

form에서 한번에 여러 파일을 보내면 MultipartHttpServletRequest files로 받는다.

받고, .getFiles("name명")를 통해 찾아 List<MultipartFile>에 담고 for문을 돌린다.

for문 안의 내용은 단일파일을 받을 때와 동일하다.

 

저장폴더에는 선택된 파일들이 한번에 저장됨.


복수태그로 여러파일 업로드

@RequestParam으로 list를 받음

<input type="file" />태그가 3개일 때, 파일을 하나만 올린다면?
빈값으로 list가 생성됨
파일 자체 내용이 없다.
잘못된 파일 형태로 남게 됨.

=>
빈값은 제거

list.stream().filter((x)->x.isEmpty()==false ).collect(Collectors.toList());

 

-stream()으로 stream타입 반환.
-filter는 js의 filter와 동일. true인 값만 받아서 새로운 list로.
-collect()는 수집함수. 새로운 list모양으로 반환을 받는 것.

 

 

 

 

html

<h3>복수태그로 여러파일 업로드</h3>
<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="업로드"/><br/>
</form>

 

 

 

Controller

@Value("${project.uploadpath}")
private String uploadpath;

//날짜별로 폴더생성
public String makeDir() {
	Date date=new Date();
	SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
	String now=sdf.format(date);

	String path=uploadpath + "\\" +now; //경로
	File file = new File(path);

	if(file.exists()==false) {//파일이 존재하면 true
		file.mkdir(); //폴더생성
	}

	return path;
}

//복수태그로 여러파일 업로드
	@PostMapping("/upload_ok3")
	public String uploadOk3(@RequestParam("file") List<MultipartFile> list) {
		
		//리스트에서 빈값은 제거
		list=list.stream().filter((x)->x.isEmpty()==false ).collect(Collectors.toList());
		
		for(MultipartFile file:list) {
			//파일명
			String origin = file.getOriginalFilename(); 
			//브라우저별로 경로가 포함되서 올라오는 경우가 있기에 간단한 처리.
			String filename=origin.substring(origin.lastIndexOf("\\")+1); 
			//폴더생성
			String filepath=makeDir();
			//중복파일의 처리
			String uuid=UUID.randomUUID().toString();
			//최종저장경로
			String savename=filepath+"\\"+uuid+"_"+filename;
			try {
				File save = new File(savename); //세이브경로
				file.transferTo(save);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		return "upload/ex01_ok";
	}

 

파일을 업로드할 수 있는 input태그가 여러개일 때(같은 name으로 묶여 있다), 컨트롤러에서 받을 때는

@RequestParam("input태그 이름") List<MultipartFile> list로 받는다.

 

이때, 어떤 input은 파일을 업로드하지 않을 수도 있다. 

//리스트에서 빈값은 제거
list=list.stream().filter((x)->x.isEmpty()==false ).collect(Collectors.toList());

를 통해 처리.