학원/SPRING

12/22 70-3 [SPRING] FileUpload

도원결의 2022. 12. 22. 23:18

공포의 파일...

이건 왜 할 때마다 멘붕이냐

적응이 안됨...

 

우선 몇 가지 사전작업을 하고 들어가자

파일 업로드하기 위해서는 라이브러리를 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>

 

천천히 보면 이해를 조오오오큼 할거 같은데

막상 직접 하려하면

눈앞이 캄캄캄

에휴