파일 전송을 위한 의존성 설정
pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
서블릿 3.0이상 버전 설정
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">//버전변경
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml
</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<!-- 첨부파일 설정========================================================================= -->
<multipart-config>
<location>C:\\upload\\temp</location><!-- 파일이 저장 될 공간 -->
<max-file-size>20971520</max-file-size> <!--1MB * 20 --><!-- 업로드 되는 파일의 최대크기 -->
<max-request-size>41943040</max-request-size><!-- 40MB --><!-- 한번에 올릴 수 있는 최대크기 -->
<file-size-threshold>20971520</file-size-threshold> <!-- 20MB -->
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 한글 인코딩 설정 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- <filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-->
</web-app>
web.xml 또한 버전을 3.0이상으로 변경 및 <multipart-config> 추가
servlet-context.xml
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"></beans:bean>
첨부파일 처리하는 빈 추가
Form 을 이용한 파일전송 테스트
uploadForm.jsp
<body>
<form action="uploadFormAction" method="post" enctype="multipart/form-data">
<input type='file' name='uploadFile' multiple>
<button>전송</button>
</form>
</body>
enctype 속성값을 multipart/from-data 지정해야하며
최근 브라우저에서는 multiple 이라는 속성을 지원하여 여러개의 파일을 업로드 할 수 있음(ie10 이상에서만 지원)
UploadController
@PostMapping("/uploadFormAction")
public void uploadFormAction(MultipartFile[] uploadFile, Model model) {
String uploadFolder = "C:\\upload1";
for(MultipartFile multipartFile:uploadFile) {
log.info("==========");
log.info("업로드 파일이름: "+multipartFile.getOriginalFilename());
log.info("업로드 파일크기: "+multipartFile.getSize());
File saveFile = new File(uploadFolder, multipartFile.getOriginalFilename());
try {
multipartFile.transferTo(saveFile);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
여러개의 파일을 업로드 할 수 있기때문에 MultipartFile의 배열 타입으로 받으며
업로된 파일을 transferTo() 의 파라미터로 File 객체를 지정하여 파일을 저장한다.
콘솔과 함께 파일이 서버에 저장됨을 확인 할 수 있다.
Ajax를 이용한 파일전송 테스트
uploadAjax.jsp
<div class='uploadDiv'>
<input type='file' name='uploadFile' multiple>
</div>
<button id='uploadBtn'>Upload</button>
JQuery를 쓰기위해 cdn 선언
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script>
$("#uploadBtn").on("click", function(e) {
var formData = new FormData();
var formData = new FormData();
var inputFile = $("input[name='uploadFile']");
var files = inputFile[0].files;
//console.log(files);
for (var i = 0; i < files.length; i++) {
if (!checkExtension(files[i].name, files[i].size)) {
return false;
}
formData.append("uploadFile", files[i]);
}
$.ajax({
url : '/uploadAjaxAction',
processData : false,
contentType : false,
data : formData,
type : 'POST',
dataType : 'json',
success : function(result) {
console.log(result);
showUploadedFile(result);
$(".uploadDiv").html(cloneObj.html());
}
}); //$.ajax
});
ajax를 통해서 JSON타입으로 formData에 정보를 담아서 전송한다.
processData와 contentType은 반드시 false로 지정한다,
UploadController
//파일 저장
@PostMapping(value="/uploadAjaxAction", produces= MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public ResponseEntity<List<AttachFileDTO>>uploadAjaxPost(MultipartFile[] uploadFile){
//파일 여러개->배열형태
List<AttachFileDTO> list = new ArrayList<>();
String uploadFolder = "C:\\upload1";
//getFolder 메서드로 폴더 패턴 생성
String uploadFolerPath = getFolder();
//폴더 만들기(부모,자식)
File uploadPath = new File(uploadFolder,uploadFolerPath);
//업로드 폴더가 존재하지 않는다면 만들어준다.
if(uploadPath.exists() == false) {
uploadPath.mkdirs();
}
for(MultipartFile multipartFile : uploadFile) {
AttachFileDTO dto = new AttachFileDTO();
String uploadFileName = multipartFile.getOriginalFilename();
//ie의 경우 전체 파일 경로가 전송됨으로 \\까지 제외한 문자열이 실제 파일이름으로 저장
uploadFileName =uploadFileName.substring(uploadFileName.lastIndexOf("\\")+1);
log.info("오직 파일 이름만: "+uploadFileName);
dto.setFileName(uploadFileName);
//중복방지 uuid 적용==========================================================
UUID uuid = UUID.randomUUID();
//[uuid랜덤값_파일 본래이름]
uploadFileName = uuid.toString()+"_"+uploadFileName;
try {
//브라우저에서 업로드된 파일을 서버내에 생성(부모,자식)
File saveFile = new File(uploadPath, uploadFileName);
//브라우저에서 업로드받은 파일을 서버의 파일 도착지인 saveFile로 transferTo 을 이용해 전송
multipartFile.transferTo(saveFile);
dto.setUuid(uuid.toString());
dto.setUploadPath(uploadFolerPath);
//업로드된 파일이 이미지이면 썸네일 파일하나를 더 생성해준다.
if(checkImageType(saveFile)) {
dto.setImage(true);
FileOutputStream thumbnail = new FileOutputStream(new File(uploadPath, "s_"+uploadFileName));
//Thumbnailator이용 파일생성->파라미터값으로 weight height 지정 가능
Thumbnailator.createThumbnail(multipartFile.getInputStream(), thumbnail,100,100);
thumbnail.close();
}
list.add(dto);
} catch (Exception e) {
e.printStackTrace();
}
}//End for
return new ResponseEntity<>(list,HttpStatus.OK);
}
파일이 서버에 들어옴을 확인 할 수 있다.
파일 업로드의 크기제한
정규식을 이용하여 파일 업로드의 제한을 걸자
//업로드 파일 타입 제한==============================================================
var regex = new RegExp("(.*?)\.exe|sh|zip|alz$");
var maxSize = 5242880; // 5mb
//파일 타입,용량 확인 메서드======================
function checkExtension(fileName, fileSize){
if(fileSize >= maxSize){
alert("파일 용량 초과");
return false;
}
if(regex.test(fileName)){
alert("업로드 될수 없는 타입입니다.");
return false;
}
return true;
}
//파일타입의 변경유무가 있을시(파일을 업로드시)========================================================================
$("input[type='file']").change(function(e){
var formData = new FormData();
var inputFile = $("input[name='uploadFile']");
var files = inputFile[0].files;
for(var i=0; i<files[i].length; i++){
//확인 메서드에서 false가 나오면 안됨
if(!checkExtension(files[i].name, files[i].size)){
return false;
}
//append:요소추가
formData.append("uploadFile",files[i]);
}
//ajax로 서버(uploadAjaxAction)에 전송
$.ajax({
url: '/uploadAjaxAction1',
processData: false,
contentType: false,
data: formData,
type: 'POST',
dataType: 'json',
success: function(result){
console.log(result)
showUploadResult(result);
}
}); // End ajax
}); //End change
uploadController
년/월/일 형식의 폴더를 생성하여 업로된 파일을 그에 맞게 저장하게 설정 하였다.
@PostMapping("/uploadAjaxAction1")
public void uploadFormAction(MultipartFile[] uploadFile, Model model) {
String uploadFolder = "C:\\upload1";
File uploadPath = new File(uploadFolder,getFolder());
log.info(uploadPath);
if(uploadPath.exists() == false) {
uploadPath.mkdirs();
}
for(MultipartFile multipartFile : uploadFile) {
log.info("==========");
log.info("업로드 파일이름: "+multipartFile.getOriginalFilename());
log.info("업로드 파일크기: "+multipartFile.getSize());
String uploadFileName = multipartFile.getOriginalFilename();
//IE
uploadFileName = uploadFileName.substring(uploadFileName.lastIndexOf("\\")+1);
log.info(uploadFileName);
File saveFile = new File(uploadPath, uploadFileName);
try {
multipartFile.transferTo(saveFile);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
해당 날짜폴더에 업로드된 파일을 확인 할 수 있음
그러나 똑같은 파일의 이름을 업로드시 구분하기 어렵기 때에 uuid를 적용시켜서 파일 고유 이름으로 저장하게 바꾸어 보자
uuid적용
//중복방지 uuid 적용==========================================================
UUID uuid = UUID.randomUUID();
//[uuid랜덤값_파일 본래이름]
uploadFileName = uuid.toString()+"_"+uploadFileName;
try {
//브라우저에서 업로드된 파일을 서버내에 생성(부모,자식)
File saveFile = new File(uploadPath, uploadFileName);
위의 기존코드에서 조금 수정되었다
uploadFileName을 uuid로 적용시켜서 File객체에 넣어주자
uuid가 적용됨을 확인 할 수 있다.
'SPRING > 스프링' 카테고리의 다른 글
[스프링]21. 로그인된 사용자의 정보 출력하기(feat.스프링 시큐리티) (0) | 2021.06.10 |
---|---|
[스프링]20. summernote를 이용한 글쓰기 폼 구현 (0) | 2021.05.31 |
이클립스 깃허브 nothing to fetch 오류 (0) | 2021.05.07 |
[스프링] 18. 자바 코드 또는 XML 설정 (0) | 2021.05.03 |
[스프링]17. 스프링 컨테이너에 대하여 // 스프링 빈 조회 TEST (0) | 2021.05.01 |