Spring 파일 업로드 API

채상혁·2022년 2월 18일
1

Spring

목록 보기
16/18

오늘 스프링 파일 업로드에 대해서 배웠다.

  1. mvn-repository 에서 api를 가져와서 pom.xml에 작성.

  2. 파일 업로드 설정 servlet-config.xml에 작성

	<!-- 파일 업로드 -->
	<!-- 반드시 id를 multipartResolver로 선언
		MultiPart형식으로 전달되는 데이터를 스프링 mvc에서 사용할 수 있도록 변환해 주는 객체  -->
	<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		
		<!-- 최대 업로드 가능한 바이트 크기(바이트 단위), -1은 제한이 없음을 의미 -->
		<beans:property name="maxUploadSize" value="10485760"/>

		<beans:property name="defaultEncoding" value="utf-8"/>	
	</beans:bean>
	

3.파일 업로드 폼 만들기 ex> upload.jsp

<!--file 업로드에서는 ecntype를 multipart/form-data로 반드시 설정  -->
	<form action="upload_ok" method="post" enctype="multipart/form-data">
		파일 선택 : <input type="file" name="file"> <br>
		<input type="submit" value="전송">
	</form>
	<hr>

	<form action="upload_ok2" method="post" enctype="multipart/form-data">
		파일선택 : <input type="file" multiple="multiple" name="files"> <br>
		<input type="submit" value="전송">
	</form>
	
	<hr>
	
	<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="전송">
	</form>
	
	<hr>
	
	<form action="upload_ok4" method="post" enctype="multipart/form-data">
		원하시는 파일명 : <input type="text" name="list[0].name">
		파일 선택 : <input type="file" name="list[0].file">
		<br>

		원하시는 파일명 : <input type="text" name="list[1].name">
		파일 선택 : <input type="file" name="list[1].file">
		<br>
		원하시는 파일명 : <input type="text" name="list[2].name">
		파일 선택 : <input type="file" name="list[2].file">
		<br>
		<input type="submit" value="전송">
	</form>

파일을 하나만 받을때, 여러개 받을때, 여러개를 다른 이름으로 받을때.

파일을 받기 위해 DB와 관련되어있는 UploadVO

import org.springframework.web.multipart.MultipartFile;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class UploadVO {

	private String name;
	private MultipartFile file;
	
}

위쪽 폼으로 연결 및 제어하는 컨트롤러.

package com.spring.myweb.controller;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

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.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.spring.myweb.command.MultiUploadVO;
import com.spring.myweb.command.UploadVO;

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

	@GetMapping("/upload")
	public void form() {}
	
	@PostMapping("/upload_ok")
	public String upload(@RequestParam("file") MultipartFile file) {
		try {
			String fileRealName = file.getOriginalFilename(); //파일명
			long size = file.getSize(); //파일 사이즈
			
			System.out.println("파일명:" + fileRealName);
			System.out.println("파일 사이즈:" + size);
			
			//서버에서 저장할 파일 이름
			String fileExtension = fileRealName.substring(fileRealName.lastIndexOf("."),fileRealName.length());
			String uploadFolder = "C:\\test\\upload";
			
			/*
			  파일 업로드 시 파일명이 동일한 파일이 이미 존재할 수도있고,
			  사용자가 업로드하는 파일명이 영어 이외의 언어로 되어있을 수 있습니다.
			  타 언어를 지원하지 않는 환경에서는 정상 동작이 되지 않습니다. (리눅스,mysql)
			 */
			UUID uuid = UUID.randomUUID();
			String[] uuids = uuid.toString().split("-");
			String uniqueName = uuids[0];
			System.out.println("생성된 고유 문자열" + uniqueName);
			System.out.println("확장자명: " +fileExtension);
			
			
			
			File saveFile = new File(uploadFolder+ "\\" + uniqueName + fileExtension);
			//실제 파일 저장 메서드(fileWriter작업을 손쉽게 한방에 처리해 줍니다.)
			file.transferTo(saveFile);
		}  catch (Exception e) {
			e.printStackTrace();
		}
		
		return "fileupload/upload_ok";
	}
	
	@PostMapping("/upload_ok2")
	public String upload2(MultipartHttpServletRequest files) {
		//서버에서 저장할 파일 경로
		String uploadFolder = "C:\\test\\upload";
		List<MultipartFile> list =  files.getFiles("files");
		/*

		for(int i=0; i<list.size(); i++) {
			String fileRealName = list.get(i).getOriginalFilename();
			long size = list.get(i).getSize();
			System.out.println("파일명: " +fileRealName);
			System.out.println("사이즈: " + size);
			
			File saveFile = new File(uploadFolder + "\\" + fileRealName);
			try {
				list.get(i).transferTo(saveFile);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
			 */
		for(MultipartFile m : list) {
			String fileRealName = m.getOriginalFilename();
			long size = m.getSize();
			System.out.println("파일명: " +fileRealName);
			System.out.println("사이즈: " + size);
			
			File saveFile = new File(uploadFolder + "\\" + fileRealName);
			try {
				m.transferTo(saveFile);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return "fileupload/upload_ok";
	}
	
	@PostMapping("/upload_ok3")
	public String upload3(@RequestParam("file") List<MultipartFile> list) {
		
		
		
		return "fileupload/upload_ok";
	}
	
	@PostMapping("/upload_ok4")
	public String upload4(MultiUploadVO vo) {
		System.out.println(vo);
		
		String uploadFolder = "C:\\test\\upload";
		List<UploadVO> list = vo.getList();
		try {
			for(UploadVO uvo : list) {
				String fileRealName = uvo.getFile().getOriginalFilename();
				long size = uvo.getFile().getSize();
				
				File saveFile = new File(uploadFolder + "\\" +fileRealName);
				uvo.getFile().transferTo(saveFile);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return  "fileupload/upload_ok";
	}
	
	
    
   
	
	
	
	
	
	
	
}

파일을 등록하는 jquery

 $(function() {
      
      //등록하기 버튼 클릭 이벤트
      $('#uploadBtn').click(function() {
         regist();
      });
      
      //등록을 담당하는 함수
      function regist() {
         //세션에서 현재 로그인 중인 사용자 정보(아이디)를 얻어오자
         const user_id = '$(sessionScope.login.userId)';
         //자바스크립트의 파일 확장자 체크 검색.
         let file = $('#file').val();
         console.log(user_id);
         console.log(file);
         //.을 제거한 확장자만 얻어낸 후 그것을 소문자로 일괄 변경
         file = file.slice(file.indexOf('.') + 1).toLowerCase();
         if(file !== 'jpg' && file !== 'png' && file !=='jpeg' && file !=='bmp'){
        	 alert('이미지 파일만 등록이 가능합니다.');
        	 $('#file').val('');
        	 return;
         } else if(user_id === '') { //세션 데이터가 없다 -> 로그인 x
        	 alert('로그인이 필요한 서비스입니다.');
             return;
        	 
         }
         
         //ajax 폼 전송의 핵심 FormData 객체.
         const formData = new FormData();
         const data = $('#file');
         
         console.log('폼 데이터 : ' + formData);
         console.log('data : '+ data);
         console.log(data[0]); //파일 태그에 담긴 파일 정보를 확인하는 키값.
         console.log(data[0].files[0]);
         
         //data[index] -> 파일 업로드 버튼이 여러 개 존재할 경우 요소의 인덱스를 지목해서 가져오는 법.
         //우리는 요소를 id로 취득헀기 때문에 하나만 찍히지만, class이름 같은거로 지목하면 여러개가 취득되겠죠?
         //files[index] -> 파일이 여러개 전송되는 경우, 몇 번째 파일인지를 지목.
         //우리는 multiple 속성을 주지 않았기 때문에 0번 인덱스 밖에 없는 겁니다.
         
         //FormData 객체에 사용자가 업로드한 파일의 정보들이 들어있는 객체를 전달.
         formData.append('file',data[0].files[0]);
         //content(글 내용) 값을 얻어와서 폼 데이터에 추가
         const content = $('#content').val();
         formData.append('content',content);
         
         //비동기 방식으로 파일 업로드 및 게시글 등록을 진행/
         $.ajax({
        	 url : '<c:url value="/snsBoard/upload"/>',
        	 type : 'post',
        	 data : formData, //폼 데이터 객체를 넘깁니다.넘깁니다.
        	 contentType : false,//ajax방식에서 파일을 넘길 떄는 반드시 false로 처리 -> "multipart/form-data"로 선언됨.
        	 processData : false, //폼 데이터를 &변수=값&변수=값 ... 형식으로 변경되는 것을 막는 요소.
        	 success : function(result){
        			 
        	 },
        	 error : function(request,status,error){
        		 console.log('code :'+ request + '\n' + request.responseText + '\n' + 'error :' +error);
        		 alert('업로드에 실패했습니다. 관리자에게 문의해 주세요.')
        	 }
        	 
         }); // end ajax
         
      }
      
   });
   

파일 미리보기 기능

    //자바 스크립트 파일 미리보기 기능
      function readURL(input) {
           if (input.files && input.files[0]) {
              
               var reader = new FileReader(); //비동기처리를 위한 파읽을 읽는 자바스크립트 객체
               //readAsDataURL 메서드는 컨텐츠를 특정 Blob 이나 File에서 읽어 오는 역할 (MDN참조)
              reader.readAsDataURL(input.files[0]); 
               //파일업로드시 화면에 숨겨져있는 클래스fileDiv를 보이게한다
               $(".fileDiv").css("display", "block");
               
               reader.onload = function(event) { //읽기 동작이 성공적으로 완료 되었을 때 실행되는 익명함수
                   $('#fileImg').attr("src", event.target.result); 
                   console.log(event.target)//event.target은 이벤트로 선택된 요소를 의미
              }
           }
       }
      $("#file").change(function() {
           readURL(this); //this는 #file자신 태그를 의미
           
       });

0개의 댓글