230221 Spring Boot 파일 업로드 방식
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로 받는다.
폴더와 이름까지 지정됨. 페이지는 성공하면 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());
를 통해 처리.