Jam's story

[Spring] 파일업로드 본문

Spring

[Spring] 파일업로드

애플쩀 2022. 7. 15. 15:44

1️⃣  form enctype="multipart/form-data" method="post" 설정 

     ✨폼태그 코딩이 이렇게 되어있는지 확인하기 

 

2️⃣멀티 파트 형식으로 데이터 (첨부파일) 가 전송이 되면 스프링 MVC 에서 사용할 수 있도록 변환해주는 객체 - MultipartResover 스프링 빈으로 등록

  • CommonMultipartResolver - Commons FileUpload API 이용해서 데이터 처리 +++ (수업)
  • StandardServletmultipartResolver - 서블릿 3.0 의 Part 이용해서 데이터 처리

3️⃣ 주의할 점

  • MultipartResover 스프링 빈으로 등록할 때 반드시 이름 "multipartResolver" 라고 설정.
  • DispatcherServlet 프론트 컨트롤러에서 해당이름으로 처리하도록 코딩되어져있기 때문.
  1. 2-2. 스프링이 기본 제공하는 MultipartResover 2가지 종류
  2. 서버 재시작 (restart)
  3. 업로드 파일 접근하는 방법 (4가지)
    • MultipartFile 인터페이스 이용
      • 컨트롤러 메서드
      • RequestMapping()
      • public String upload(MultipartFile multipartFile) { }
      • File 파일객체 = new File(파일경로)
      • 첨부된 파일 유무 - multipartFile.transferTo(파일객체)
    • RequestParam 어노테이션을 이용
      • <input type="file" name="f">
ㄱ. MultiparFile 인터페이스 이용
               컨트롤러 메서드 
               @RequestMapping()
               public String upload( MultiparFile multiparFile  ){
                    File 파일객체 = new File(파일경로);
                     첨부된 파일 유무 -  multiparFile.tansferTo( 파일 객체 );
               }
         ㄴ. @RequestParam 어노트페이션을 이용
             <input type="file" name="f">
             @RequestMapping()
               public String upload( @ReqeustParam("f")  MultiparFile multiparFile  ){
                    File 파일객체 = new File(파일경로);
                     첨부된 파일 유무 -  multiparFile.tansferTo( 파일 객체 );
               }
         ㄷ. Multipart[HttpServerRequest]을 이용
         @RequestMapping()
               public String upload(  Multipart[HttpServerRequest] mrequest ){
                     MutipartFile  mfile = mrequest.getFile("f");
                     File 파일객체 = new File(파일경로);
                     첨부된 파일 유무 -  mfile.tansferTo( 파일 객체 );
               }
         ***ㄹ.커맨드 객체를 통해 업로드 파일 접근. ***        
               1) Notice.java
               <input type="file" id="txtFile" name="file" />   
               ublic String noticeReg(  Notice notice )
               2) 필드 추가
               private CommonsMultipartFile file;
               3) MultipartFile 인터페이스 주요 메서드
                  ㄱ. String getName()                     파라미터 이름 
                  ㄴ. String getOriginalFilename() 업로드한 파일의 이름
                  ㄷ. boolean isEmpty()                       업로드한 파일 존재 유무
                  ㄹ. long getSize()                            업로드한 파일 크기
                  ㅁ. byte [] getBytes()                    업로드한 파일의 바이트 데이트
                  ㅂ. InputStream getInputStream()  업로드한 파일의 읽기 스트림 객체 반환
                  ㅅ. transferTo( File )                       업로드한 파일을 저장 
         
         ㅁ. 서블릿 3.0의 Part 이용
         @RequestMapping()
               public String upload(   @ReqeustParam("f") Part part ){
               }

 

1️⃣dispatcher-servlet.xml

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="-1"></property>
</bean>

maxUploadSize 최대 업로드 가능한 크기. 기본값 -1

maxInMemorySize 디스크에 임시파일을 생성하기 전에 메모리에 보관할 수 있는 최대바이트 크키. 기본값 1024.

defaultEncoding 기본값 ISO-8859-1

 

2️⃣NoticeReg.jsp에서 확인 

//form태그에 
<form action="" method="post"  enctype="multipart/form-data">

//파일 올리는 칸 
&nbsp;<input type="file" id="txtFile" name="file" />

 

3️⃣Notice.java

2번(NoticeReg.jsp에서 name="file" 속성명  )이랑 DTO필드명이랑 같아야한다.

	/* jsp에서 <input type="file" id="txtFile" name="file" />   */
	private CommonsMultipartFile file;
    
    public CommonsMultipartFile getFile() {
		return file;
	}
	public void setFile(CommonsMultipartFile file) {
		this.file = file;
	}

 

4️⃣컨트롤러에 noticeReg(Notice notice )메소드 추가 

 

Notice.jsp에  글쓰기 버튼을 누르면 noticeReg.htm요청을 하고, 

이에 맞는 @RequestMapping(value={"noticeReg.htm"}) 컨트롤러 메소드 실행

<a class="btn-write button" href="noticeReg.htm">글쓰기</a>

 

//글쓰기+첨부된 파일 
	@RequestMapping( value = {"noticeReg.htm"}, method = RequestMethod.POST )
    public String noticeReg(Notice notice ,HttpServletRequest request ) throws Exception {
        //1 첨부된 파일의 유무 확인 후에 파일저장 
		CommonsMultipartFile multipartFile= notice.getFile();
		
		String uploadRealPath=null;
		
		if(!multipartFile.isEmpty()) { //첨부된 파일이 있다면 
			uploadRealPath =request.getServletContext().getRealPath("/customer/upload");
			System.out.println("uplaodRealPath:"+uploadRealPath);
			
			String originalFilename=multipartFile.getOriginalFilename(); //오천 "a.txt" ->"a_1.txt"
			//이렇게 인덱스를 붙이는 함수 (이미 존재할 수 도 있으니까)
		    String filesystemName = getFileNameCheck(uploadRealPath, originalFilename);
			File dest=new File(uploadRealPath,filesystemName);
			multipartFile.transferTo(dest); //실질적으로 파일을 저장 
			
			//originalFilename ,  filesystemName Notices 테이블의 칼럼이 2개 존재 
			String filesrc=filesystemName; //저장하고자하는 파일 
			notice.setFilesrc(filesrc);
		}
		//2.Notices 테이블에 공지사항 INSERT
		notice.setWriter("kenik");
         int rowCount = this.noticeDao.insert(notice);
         if (rowCount==1) { 
            return "redirect:notice.htm";         
         }else { 
            return "redirect:noticeReg.jsp?error"; 
         }
   } // noticeReg
   
   	//순수한 파일명+인덱스추가 만드는 메소드 
	private String getFileNameCheck(String uploadRealPath, String originalFilename) {
		   int index = 1;
		    while(true) {
		        File f = new File(uploadRealPath, originalFilename); // 파일객체
		        if( !f.exists()) return originalFilename;    
		        String fileName=originalFilename.substring(0,originalFilename.length()-4);
		        String ext=originalFilename.substring(originalFilename.length()-4);
		        
		        originalFilename = fileName+"-"+(index)+ext;
		          index++;
		    } // while 문 닫기
	}

 

5️⃣customer 폴더 밑에 upload 폴더 추가 


다운로드할때 텍스트나 이미지는 다운로드가 되지 않고, 브라우저가 열리면서 보인다.

다운로드가 되도록

 

1️⃣noticeDetail.jsp 수정

 

<a href="download.htm?p=customer/upload&f=${ notice.filesrc }">${ notice.filesrc }</a>

 

2️⃣컨트롤러 수정

기존 헤더에 추가려하려는 것과 같은 키값이 존재할 경우.
   
addHeader() : 그 키에 해당하는 값을 하나 더 추가한다.
setHeader() : 새롭게 설정한 값으로 덮어 쓴다.
	// 컨트롤러 메서드 선언
	   // download.htm
	   //?
	    //p=customer/upload    경로
	   //&
	   //f=다운로드할 파일명
	//이미지나 텍스트파일이 바로 펼쳐지지않게 
	   @RequestMapping("download.htm")
	   public void download (
	           HttpServletResponse response
	           , HttpServletRequest request
	           , @RequestParam("p") String p
	           , @RequestParam("f") String f
	         ) throws Exception{
	      
	      // 이창익(서버)     ->       함세강(클라이언트 즉, 브라우저)
	      //  아이스크림     응답 ->     먹었다. 
	      // 표지 [ 상자 :아이스크림 ]   응답 ->     X   저장 대화상자 띄운다.
	      // 응답 헤드 X
	      
	      String fname =  f;  
	      response.setHeader("Content-Disposition","attachment;filename="+
          new String(fname.getBytes(), "ISO8859_1"));      
	       
	      String fullPath = request.getServletContext().getRealPath(   p + "/" + fname);
	    
	      FileInputStream fin = new FileInputStream(fullPath);//읽어올 파일 지정 
	      ServletOutputStream sout = response.getOutputStream(); // 응답 스트림
	      byte[] buf = new byte[1024];
	      int size = 0;
	      while((size = fin.read(buf, 0, 1024)) != -1) {
	         sout.write(buf, 0, size); 
	      }
	      fin.close();
	      sout.close();
	      
	   } // download

글 수정할때 

 

noticeDetail.jsp

	<a class="btn-edit button" href="noticeEdit.htm?seq=${notice.seq}">수정</a>

 

 

@RequestMapping(value = {"noticeEdit.htm"}, method = RequestMethod.POST)
public String noticeEdit(
    Notice notice
    , @RequestParam("oFilesrc") String oFilesrc // 원래 첨부파일 유무 체크
    , HttpServletRequest request
) throws Exception {
    String uploadRealPath = request.getServletContext().getRealPath("/customer/upload");
    CommonsMultipartFile multipartFile = notice.getFile();

    if (!multipartFile.isEmpty()) { // 새로 첨부파일 있다면
        // 원래 첨부된 파일이 있다면 삭제.
        File delOFile = new File(uploadRealPath, oFilesrc);

        if (delOFile.exists()) {
            delOFile.delete();
        }
        // ㄱ. upload 폴더 - 저장
        System.out.println("> uploadRealPath: " + uploadRealPath);
        String originalFilename = multipartFile.getOriginalFilename(); // a.txt
        originalFilename = getFileNameCheck(uploadRealPath, originalFilename);
        File dest = new File(uploadRealPath, originalFilename);
        multipartFile.transferTo(dest); // 업로드 폴더에 파일 저장.

        // ㄴ. notice.filesrc 업로드된 파일이름 저장: a.txt -> [a-1.txt]
        notice.setFilesrc(originalFilename);
    } else { // 새로 첨부파일 있다면
        notice.setFilesrc(oFilesrc);
    }
    int rowCount = noticeDao.update(notice);
    return "redirect:noticeDetail.htm?seq=" + notice.getSeq();
}

 


삭제

1️⃣ NoticeDetail.jsp

	<a class="btn-del button" href="noticeDel.htm?seq=${notice.seq}&filesrc=${notice.filesrc}">삭제</a>

2️⃣

@RequestMapping(value= {"noticeDel.htm"})
public String noticeDel(String seq ,String filesrc,  HttpServletRequest request) throws Exception{
//1 첨부파일이 있을 경우엔 첨부파일을 upload 폴더 삭제 
	//서버 배포 실제 경로
	String uploadRealPath =request.getServletContext().getRealPath("/customer/upload");
	/* 
	 * 첨부파일을 select 알아야 왔다. 
	Notice notice=this.noticeDao.getNotice(seq);
	String filesrc=notice.getFilesrc();
	if(filesrc !=null) {
		File delFile=new File( uploadRealPath, filesrc);
		delFile.delete();
	}
	*/
	// filesrc 는 파일이 없는경우 파라미터 값 x 	
	File delFile=new File( uploadRealPath, filesrc);
	if(delFile.exists() ) {delFile.delete();}
	
	//2
	int rowCount=this.noticeDao.delete(seq);
	if(rowCount==1) return "redirect:notice.htm";
	else return "redirect:noticeDetail.htm?seq"+seq;
}

 

 

 

 

Comments