https://mvnrepository.com/ 에서
1) commons-fileupload 검색 - 1.4 클릭 - 중간 코드 복사 - pom.xml에 붙여넣기
2) imgscalr-lib 검색 - Imgscalr A Java Image Scaling Library » 4.2 클릭 - 중간 코드 복사 - pom.xml에 붙여넣기
3) jackson-databind 검색 - 2.13.1 클릭 - 중간코드 복사 - pom.xml에 붙여넣기
4) thumbnailator 검색 0.4.16 -> 중간코드 복사 -> pom.xml에 붙여넣기
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>kr.or</groupId>
<artifactId>ddit</artifactId>
<name>springProj</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.8</java-version>
<org.springframework-version>5.2.5.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<!-- Database 라이브러리 시작 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<!-- XML로 쿼리를 작성하게 해주는 라이브러리 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<!-- 스프링과 mybatis를 연동하게 해주는 라이브러리 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<!-- 스프링에서 JDBC 드라이버를 통해 DB 연결 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
<!--
데이터베이스 커넥션 풀. 커넥션을 미리 여려개 만들어 놓고, 빌려썼다가 사용이 끝나면 반납.
최근에 hikaricp를 사용하는 경우도 있음
-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.9.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bgee.log4jdbc-log4j2/log4jdbc-log4j2-jdbc4 -->
<!-- Logging을 위한 라이브러리. Query를 Console이나 파일 로그로 볼 수 있음 -->
<dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4</artifactId>
<version>1.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc6 -->
<!-- 오라클과 자바를 연결해주는 라이브러리 -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<!--
* 자바빈 클래스인 VO에서 Getter/Setter메서드, toString()메서드를 자동 생성
-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
<!-- Database 라이브러리 끝 -->
<!-- 입력값을 검증하기 위한 라이브러리 의존 관계 정의 -->
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.2.Final</version>
</dependency>
<!-- 파일 업로드 라이브러리 시작 -->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<!-- 파일 업로드/다운로드 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.imgscalr/imgscalr-lib -->
<!-- 썸네일 -->
<dependency>
<groupId>org.imgscalr</groupId>
<artifactId>imgscalr-lib</artifactId>
<version>4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.16</version>
</dependency>
<!-- 파일 업로드 라이브러리 끝 -->
<!-- json 데이터 바인딩을 위한 의존 라이브러리 -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
1) 구글에서 web.xml web-app 3.1검색
https://antop.tistory.com/entry/webxml-%EC%84%9C%EB%B8%94%EB%A6%BF-%EB%B2%84%EC%A0%84%EB%B3%84-DTD 에서 servlet 3.1 코드 복사
(1)web.xml에서 아래와 같이 바꾸기
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
2)<servlet> 안에 아래 코드 추가
<!-- 파일업로드 설정 시작 -->
<multipart-config>
<location>C:\\upload</location> <!-- 업로드 되는 파일을 저장할 공간 -->
<max-file-size>20971520</max-file-size><!-- 업로드 최대크기 1MB * 20 (= 20MB)으로 지정 -->
<max-request-size>41943040</max-request-size><!-- 한번에 올릴 수 있는 최대 크기 1MB * 40 (= 40MB)으로 지정-->
<file-size-threshold>20971520</file-size-threshold><!-- 메모리 사용 1MB * 20 (= 20MB)으로 지정 -->
</multipart-config>
<!-- 파일업로드 설정 끝 -->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
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>
<!-- web.xml 설정 : Tomcat 자체 설정 -->
<!-- 파일업로드 설정 시작 -->
<multipart-config>
<location>C:\\upload</location> <!-- 업로드 되는 파일을 저장할 공간 -->
<max-file-size>20971520</max-file-size><!-- 업로드 최대크기 1MB * 20 (= 20MB)으로 지정 -->
<max-request-size>41943040</max-request-size><!-- 한번에 올릴 수 있는 최대 크기 1MB * 40 (= 40MB)으로 지정-->
<file-size-threshold>20971520</file-size-threshold><!-- 메모리 사용 1MB * 20 (= 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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 한글설정 END -->
</web-app>
1) 아래 코드 추가하기
view단에서 multipart/form-data 방식으로 서버에 전송되는 데이터를 스프링 MVC의 multipartResolver로 처리할 수 있다.
<!-- 첨부파일을 처리하는 빈 설정 -->
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</beans:bean>
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<!-- 정적 폴더 -> images, js, css와 같은 폴더들이 resources 밑에 들어감-->
<resources mapping="/resources/**" location="/resources/" />
<!-- 컨트롤러에서 return되는 string값(파일명) 앞 뒤로 조립되는 값 -->
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<!-- prefix는 앞, suffix는 뒤에 붙는다 (ViewResolver가 조립해준다)-->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="kr.or.ddit" />
<!-- 첨부파일을 처리하는 빈 설정 -->
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</beans:bean>
</beans:beans>
1) 아래 코드 추가하기
<Context allowCasualMultipartParsing="true" path="/">
<Resources cashingAllowed="true" cacheMaxSize="100000" />
context.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--><!-- The contents of this file will be loaded for each web application -->
<Context allowCasualMultipartParsing="true" path="/">
<Resources cashingAllowed="true" cacheMaxSize="100000" />
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
</Context>
서버에 파일 저장 시 고려할 사항
1. 파일 업로드 방식 (Post? Ajax?)
2. 파일 이름 중복으로 인한 덮어쓰기 문제 -> UUID로 해결
3. 파일 저장 경로
-> 폴더 내 파일 개수가 너무 많아지면 속도가 저하되므로,
업로드 되는 시점별로 폴더를 생성하여 파일을 관리한다.
4. 이미지 파일인 경우 썸네일 생성하기
-> 이미지 파일은 저장된 파일을 다시 화면에 보여줄 때, 썸네일 파일을 보여주게 된다.
따라서 이미지 파일을 서버에 저장 시 추가적으로 그 이미지 파일의 썸네일 파일을 생성해주어야 한다.
-> 처음에 추가했던 imgsclar-lib 라이브러리가 이미지 썸네일 생성을 해준다.
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>파일 업로드 테스트</title>
</head>
<body>
<!-- 여러 파일 업로드 시 enctype="multipart-form-data" 필수! -->
<form action="/uploadTest/uploadFormAction" method="post" enctype="multipart/form-data">
<input type="file" name="uploadFile" multiple />
<button>Submit</button>
</form>
</body>
<html>
package kr.or.ddit;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import net.coobird.thumbnailator.Thumbnailator;
@RequestMapping("/uploadTest")
@Controller
public class UploadController {
private static final Logger logger = LoggerFactory.getLogger(UploadController.class);
//jsp의 <input name="uploadFile"과 MultipartFile[]의 uploadFile 이름이 같아야 함
//MultipartFile[] --> 여러개의 파일을 올리기 위한 배열, jsp에 enctype="multipart/form-data" 필수
@PostMapping("/uploadFormAction")
public String uploadFormPost(MultipartFile[] uploadFile, Model model) {
//파일 저장경로 설정
String uploadFolder = "D:\\A_TeachingMaterial\\6.JspSpring\\workspace\\springProj\\src\\main\\webapp\\resources\\upload";
//아직 db연동 안해서 list로 한다
List<String> list = new ArrayList<String>();
for(MultipartFile multipartFile : uploadFile) {
logger.info("---------------");
logger.info("파일명 : " + multipartFile.getOriginalFilename());
logger.info("파일 크기 : " + multipartFile.getSize());
//"c:\\upload\\비숑.jpg" 으로 조립
//이렇게 업로드 하겠다 라고 설계
File saveFile = new File(uploardFolder, multipartFile.getOriginalFilename());
try{
//transfer하기 전에 파일 실제 명을 list에 담음
list.add(multipartFile.getOriginalFilename());
//transferTo() : 물리적으로 파일 업로드가 되는 시점이 여기!
multipartFile.transferTo(saveFile);
}catch(Exception e){
logger.info(e.getMessage());
}//end catch
}//end for
//forwarding 하기 전 model에 list를 담는다.
// 이 list에는 파일명들이 들어 있다.
//forward
return "uploadTest/uploadSuccess";
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>업로드 성공</title>
</head>
<body>
업로드 성공! <br>
<c:forEach var="img" items="${list}">
<img src="/resources/upload/${img}" />
</c:forEach>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<title>Upload with Ajax</title>
<script type="text/javascript">
//파일을 담아두는 변수
var sel_file = [];
$(function(){
//------------ 이미지 미리보기 시작 ---------------
$("input_img").on("change", handleImgFileSelect);
function handleImgFileSelect(e){
//e.target : 파일 객체
//e.target.files : 파일 객체 안의 파일들
var files = e.target.files;
//파일을 잘라서 array로 만든다!
var filesArr = Array.prototypes.slice.call(files);
//f: 파일 객체
filesArr.forEach(function(f){
//미리보기는 이미지만 가능
if(!f.type.match("image.*")){
alert("이미지만 가능합니다.");
return;
}
//파일 객체 복사
sel_file.push(f);
//파일을 읽어주는 객체를 생성한다.
var reader = new FileReader();
reader.onload = function(e) {
//하나라면
//$("#img").attr("src", e.target.result);
//복수라면
//forEach 반복하면서 img 객체 생성하기
var img_html = "<img src=\"" + e.target.result + "\" />";
$(".img_wrap").append(img_html);
}
//reader객체에 파일URL읽어서 넣는다. -> 읽어와지면 onload 실행
reader.readAsDataURL(f);
});
//------------ 이미지 미리보기 끝 ---------------
//모든 파일명.확장자(exe|sh|zip|alz)는 업로드를 못하도록 막는다.
//첨부파일의 확장자가 exe, sh, zip, alz인 경우 업로드를 제한
var regex = new RegExp("(.*?)\.(exe|sh|zip|alz)");
//최대 5MB까지만 업로드 가능
var maxSize = 5242880; //5MB
//확장자, 크기 체크
function checkExtension(fileName, fileSize){
if(fileSize >= maxSize){
alert("파일 사이즈 초과");
return false;
}
if(regex.test(fileName)){
alert("해당 종류의 파일은 업로드할 수 없습니다.");
return false;
}
//체크 통과
return true;
}
//Upload 클릭시 이벤트 발생시키기!
$("upload").on("click", function(e){
//잘 넘어오는지 확인
//alert("왔네!");
//FormData : 가상의 <form>태그
//Ajax를 이용하는 파일 업로드는 FormData를 이용해서
var formData = new FormData();
//<input type="file" name="uploadFile" multiple /> 찾아가기
var inputFile = $("input[name='uploadFile']");
//<input type="file" 요소 내의 이미지들
var files = inputFile[0].files;
//console에 files안의 파일 이름 찍어보기
for(var i=0; i<files.length; i++){
console.log(files[i]);
//확장자, 크기 체크
//function checkExtension(fileName, fileSize){
if(!checkExtension(files[i].name, files[i].size) {
return false; //!true -> 실패
}
formData.append("uploadFile", files[i]);
}
//없어? 카드가 또?
//processData, contentType은 반드시 false여야 전송됨
$.ajax({
url : 'uploadTest/uploadAjaxAction',
processData : false,
contentType : false,
data : formData,
type : 'POST',
success : function(result){
//JSON을 string으로 변환해서 console에 찍어본다
console.log("result : " + JSON.stringlyfy(result));
}
});
});
});
</script>
</head>
<body>
<h1>Upload with Ajax</h1>
<div class="uploadDiv">
<input type="file" id="input_img" name="uploadFile" multiple />
</div>
<button id="uploadBtn">Upload</button>
<div class="img_wrap">
</div>
</body>
</html>
@ResponseBody
: JSON 객체 타입의 데이터를 만들어서 반환하는 용도로 사용됨
: JSON? {"id":"a001", "name":"개똥이"}
//<form>태그를 이용하던 방식과 동일한 방식으로 처리됨
//Ajax 방식으로 결과 데이터를 전달하므로 Model을 사용하지 않는다.
@ResponseBody
@PostMapping("uploadAjaxAction")
public List<AttachFileVO> uploadAjaxAction(MultipartFile[] uploadFile) {
String uploadFolder = "D:\\A_TeachingMaterial\\6.JspSpring\\workspace\\springProj\\src\\main\\webapp\\resources\\upload";
//연/월/일 폴더 생성 시작 ---------
File uploadPath = new File(uploadFolder, getFolder());
logger.info("uploadPath : " + uploadPath);
if(uploadPath.exists()==false) { //해당 경로가 없으면 생성해줘야 함
uploadPath.mkdirs();
}
//연/월/일 폴더 생성 끝 ---------
//첨부된 파일의 이름을 담을 List
List<AttachFileVO> list = new ArrayList<AttachFileVO>();
for(MultipartFile multipartFile : uploadFile) {
logger.info("-----------");
logger.info("파일명 : " + multipartFile.getOriginalFilename());
logger.info("파일크기 : " + multipartFile.getSize());
AttachFileVO attachFileVO = new AttachFileVO();
//1) fileName 세팅
attachFileVO.setFileName(multipartFile.getOriginalFilename());
//-------------------UUID 파일명 처리 시작 -----------------
//UUID : 동일한 이름으로 업로드되면 기존 파일을 지우게 되므로 이를 방지하기 위함
UUID uuid = UUID.randomUUID();
String uploadFileName = uuid.toString() + "-" + multipartFile.getOriginalFilename();
// c:\\upload\\gongu03.jpg으로 조립
// 이렇게 업로드 하겠다라고 설계 uploadFolder -> uploadPath
File saveFile = new File(uploadPath,uploadFileName);
//-------------------UUID 파일명 처리 끝 -----------------
try {
//transferTo() : 물리적으로 파일 업로드가 됨
multipartFile.transferTo(savaFile);
//2) uploadPath
attachFileVO.setUploadPath(uploadPath.getPath());
//3) UUID
attachFileVO.setUuid(uuid.toString());
//--------------------썸네일 처리 시작 -------------------
//이미지 파일인지 체킹
if(checkImageType(saveFile)) {
logger.info("이미지 파일? true");
//4) image여부
attachFileVO.setImage(true);
//uploadPath : 연/월/일이 포함된 경로
//uploadFileName : UUID가 포함된 파일명
FileOutPutStream thumbnail = new FileOutputStream(new File(uploadPath, "s_"+uploadFileName));
Thumbnailator.createThumbnail(multipartFile.getInputStream(), thumbnail, 100, 100); //사이즈
thumbnail.close();
}else {
logger.info("이미지 파일? false");
}
//--------------------썸네일 처리 끝 -------------------
//파일의 실제 명을 list에 담는다.
list.add(attachFileVO);
}catch(Exception e) {
logger.info(e.getMessage());
}//end catch
}//end for
return list;
}//end uploadAjaxAction
//첨부파일을 보관하는 폴더를 연/월/일 계층 형태로 생성
private String getFolder() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
String str = sdf.format(date);
return str.replace("-", File.separator);
}
//특정한 파일이 이미지 타입지 검사해주는 메소드
private boolean checkImageType(File file) {
try {
//file.toPath() : 파일의 전체 경로
logger.info("file.toPath() : " + file.toPath());
String contentType = Files.probeContentType(file.toPath());
logger.info("contentType : " + contentType);
//contentType이 image로 시작하면 이미지 타입이므로 true를 리턴함
return contentType.startsWith("image");
}catch(IOException e) {
e.printStackTrace();
}
return false;
}
}