12/22 70-3 [SPRING] FileUpload
공포의 파일...
이건 왜 할 때마다 멘붕이냐
적응이 안됨...
우선 몇 가지 사전작업을 하고 들어가자
파일 업로드하기 위해서는 라이브러리를 pom.xml 넣어 놔야함
<!-- 파일 업로드 관련 라이브라리 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
이렇게 넣어 놓고
CommonsMultipartResolver 빈 자바코드로 컨테이너에 등록
id는 반드시 multipartResolver로 지정 왜냐하면 파일업로드와
관련된 스프링의 다른 클래스들이 multipartResolver란 이름으로 참조하여 사용
(xml 설정파일에 등록하는 거 보다 훨씬 쉽다!!)
컨테이너
FileUpDownConfig.java
@Configuration
public class FileUpDownConfig { //빈 자바코드로 컨테이너에 등록
@Bean
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(1024*1024);//파일 최대 업로드 용량 1MB
return resolver;
}
}
그리고
업로드 할 폴더 하나 webapp폴더 아래에 생성 해 놓자
하나 더!
업로드할 때 중복된 이름의 파일을 업로드 시 이름 변경하기!
이거 저번에 게시판 할 때 받은 util 가져와서 사용할 거
util은 파일명만 좀 바꿔서 컨트롤러있는 패키지밑에다가 넣어놓자
FileUpDownUtils.java
public class FileUpDownUtils {
// [파일 이름 중복 체크용 메소드]
public static String getNewFileName(String path, String fileName) {
// fileName=원격.txt
File file = new File(path + File.separator + fileName);
if (!file.exists()) {
return fileName;
} else {
String ext = fileName.substring(fileName.lastIndexOf(".") + 1).trim();
String fileNameExcludeExt = fileName.substring(0, fileName.lastIndexOf("."));
String newFileName;
while (true) {
newFileName = "";
if (fileNameExcludeExt.indexOf("_") != -1) {// 파일명에 _가 포함됨
String[] arrFiles = fileNameExcludeExt.split("_");
String lastName = arrFiles[arrFiles.length - 1];
try {
int index = Integer.parseInt(lastName);
for (int i = 0; i < arrFiles.length; i++) {
if (i != arrFiles.length - 1)
newFileName += arrFiles[i] + "_";
else
newFileName += String.valueOf(index + 1);
}
newFileName += "." + ext;
} catch (Exception e) {
newFileName += fileNameExcludeExt + "_1." + ext;
}
} else {// _가 없음
newFileName += fileNameExcludeExt + "_1." + ext;
}
File f = new File(path + File.separator + newFileName);
if (f.exists()) {
fileNameExcludeExt = newFileName.substring(0, newFileName.lastIndexOf("."));
continue;
} else
break;
} //////////// while
return newFileName;
}
}/////////////////////
최대 업로드 용량 사이즈 설정:setMaxUploadSize(바이트) -1:무제한
용량 초과시 org.springframework.web.multipart.MaxUploadSizeExceededException 예외 발생
폼을 먼저 보자
<legend class="w-auto px-3">파일 업로드/다운로드</legend>
<a class="btn btn-info" href="<c:url value="/FileUpDown/FileList.do"/>">목록으로 가기</a>
<hr/>
<form action="<c:url value="/FileUpDown/FileUpload.do"/>"
method="post" enctype="multipart/form-data">
<div class="form-group">
<label><kbd class="lead">올린이</kbd></label> <input type="text"
value="${param.writer}" class="form-control" name="writer"
>
</div>
<div class="form-group">
<label><kbd class="lead">제목</kbd></label> <input type="text"
value="${param.title}" class="form-control" name="title"
>
</div>
<div class="form-group">
<label><kbd class="lead">첨부파일</kbd></label> <input type="file"
class="form-control-file border" name="Files" multiple
>
</div>
<button type="submit" class="btn btn-primary">업로드</button>
</form>
어휴 보니 목록도 나중에 뿌려주네 휴휴휴
컨트롤러
파일 업로드 시 MultipartFile API사용
주요 메소드:
getOriginalFilename( ) - 사용자가 올린 파일명
getSize( ) - 파일 크기(바이트)
getContentType( ) - 파일 컨텐트 타입
getName( ) - input type="file"의 name속성에 지정한 값
※MultipartFile객체의 transferTo(File f)메소드 호출만으로 업로드 처리됨.
※enctype="multipart/form-data" 일 때
Map은 input type="file"을 받지 못한다.
또한 checkbox(여러 개 선택해도)는 하나만 받는다.
map으로 받기
@Controller
public class UploadController {
1.map으로 받기
@PostMapping("/FileUpDown/FileUpload.do")
public String upload(@RequestParam Map map, //기타 파라미터 받기 용
@RequestParam List<MultipartFile> files, //파일 받기 용
HttpServletRequest req, //서버의 물리적 경로얻기 용
Model model
) throws IllegalStateException, IOException{
파일정보 저장
List<File> fileInfo= new Vector<>();
1.서버의 물리적 경로
String path = req.getSession().getServletContext().getRealPath("/upload"); // 폴더하나 생성 해놔야 겠네
System.out.println("upload 경로:"+path);
for(MultipartFile multipartFile:files) { //file 여러 개 받을 때
2.file객체 생성
//파일 이름 중복 시 이름변경
String renameFilename= FileUpDownUtils.getNewFileName(path,multipartFile.getOriginalFilename());
File file = new File(path+File.separator+renameFilename);
3.파일정보 저장
fileInfo.add(file);
4.파일 업로드
multipartFile.transferTo(file);
}
map.put("fileInfo",fileInfo);
model.addAllAttributes(map);
return "fileupdown14/UploadComplete";
}
자바빈으로 DTO받기
커멘드 객체 필요 (롬북 이용해서 간단하게 생성해 보자)
@Getter
@Setter
public class UploadCommand {
private String writer;
private String title;
private List<MultipartFile> files;
}
진짜 컨트롤러
@PostMapping("/FileUpDown/FileUpload.do")
public String upload(UploadCommand cmd,HttpServletRequest req,Model model) throws IllegalStateException, IOException {
//파일정보 저장
List<File> fileInfo=new Vector<>();
//1.서버의 물리적 경로 얻기
String path = req.getSession().getServletContext().getRealPath("/upload");
for(MultipartFile multipartFile:cmd.getFiles()) {
//2.file객체 생성
//파일 중복 시 이름변경
String renameFilename= FileUpDownUtils.getNewFileName(path,multipartFile.getOriginalFilename());
File file = new File(path+File.separator+renameFilename);
//파일정보 저장
fileInfo.add(file);
//3.파일 업로드
multipartFile.transferTo(file);
}
Map map = new HashMap();
map.put("writer",cmd.getWriter());
map.put("title",cmd.getTitle());
map.put("fileInfo",fileInfo);
model.addAllAttributes(map);
return "fileupdown14/UploadComplete";
}
}
결과 뿌려주는 뷰 생성
<legend class="w-auto px-3">파일업로드 결과</legend>
<ul class="list-unstyled">
<li>올린이 :${writer}</li>
<li>제목 :${title}</li>
</ul>
<h3>업로드한 파일 정보들</h3>
<c:forEach var="file" items="${fileInfo}">
<ul class="list-unstyled">
<li>파일명 :${file.name}</li>
<li>파일크기 :${fn:replace(Math.ceil(file.length()/1024),'.0','')}KB</li>
</ul>
</c:forEach>
천천히 보면 이해를 조오오오큼 할거 같은데
막상 직접 하려하면
눈앞이 캄캄캄
에휴