Controller의 업로드된 파일을 받도록 수정
스프링에 멀티파트 파일 리졸버(multipart file resolver) 설정
<input type="file" name="">
이 2개 이상 있을 때는 name속성에 같은 이름을 지정해야한다파일 업로드가 정상적으로 동작하기 위해서는 내가 만든 컨트롤러뿐만 아니라 이를 위해 멀티파트 리졸버 객체를 메모리에 올리는 두 개의 객체 생성 과정이 필요한 것이다.
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
p:maxUploadSize="5000000" />
commons-io-2.13.0.jar
commons-fileupload-1.5.jar
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.130</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.5/version>
</dependency>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="5000000"/> <!-- 5MB -->
</bean>
<mvc:resources location="/WEB-INF/storage/" mapping="/storage/**" />
WEB-INF 안에 생성
--------------------------index.jsp--------------------------
추가
<p><a href="/chapter06_Web/user/uploadForm">파일업로드</a></p>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
table {
border-collapse: collapse;
}
th, td {
padding: 5px;
}
</style>
</head>
<body>
<!-- 단순 submit으로 넘기기 -->
<form enctype="multipart/form-data" method="post" action="/chapter06_Web/user/upload"> <!-- 이 두가지는 꼭 약속 -->
<table border="1">
<tr>
<th>상품명</th>
<td><input type="text" name="imageName" size="35">
</td>
</tr>
<tr>
<td colspan="2">
<textarea name="imageContent" rows="10" cols="50"></textarea>
</td>
</tr>
<tr>
<td colspan="2">
<input type="file" name="img"> <!-- enctype="multipart/form-data" 타입 받기 -->
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="이미지 업로드">
<input type="reset" value="취소">
</td>
</tr>
</table>
</form>
<!-- AJax로 넘기기 -->
</body>
</html>
package user.controller;
import java.io.File;
import java.io.IOException;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
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.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import user.bean.UserImageDTO;
@Controller
@RequestMapping(value="user")
public class UserControllerUpload {
@GetMapping(value = "uploadForm")
public String uploadForm() {
return "/user/uploadForm";
}
@PostMapping(value = "upload")
public String upload(@ModelAttribute UserImageDTO userImageDTO,
@RequestParam MultipartFile img,
HttpSession session) {
// 가상 폴더(/user/storage)
/*String filePath_lier="D:\\Spring\\workspace\\chapter06_Web\\src\\main\\webapp\\WEB-INF\\storage" 아래와 같은거임 / 대신 \\*/
String filePath_lier="D:/Spring/workspace/chapter06_Web/src/main/webapp/WEB-INF/storage";
// 실제 폴더
String filePath = session.getServletContext().getRealPath("/WEB-INF/storage");
System.out.println("실제 폴더 =" + filePath);
String fileName = img.getOriginalFilename();
// 파일 생성
File file = new File(filePath, fileName);
// 파일 이동 img.transferTo(file);->try catch
try {
img.transferTo(file);
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "<img src='/chapter06_Web/storage/" + fileName + "' width='300' height='300' />";
}
}
File file = new File(filePath, fileName);
파일을 올린 것은 실제 폴더에 업로드, 대신 가상폴더에는 올라가지 않음
File file = new File(filePath_lier, fileName);
위와 같이 파일을 올리면 실제 폴더와, 가상폴더 둘 다에 올라감
package user.bean;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class UserImageDTO {
private int seq;
private String imageName;
private String imageContent;
private String image1;
}
<tr>
<td colspan="2">
<textarea name="imageContent" rows="10" cols="50"></textarea>
</td>
</tr>
<tr>
<td colspan="2">
<input type="file" name="img"> <!-- enctype="multipart/form-data" 타입 받기 -->
</td>
</tr>
// ----------------- name="img"가 2개 일때 -----------------
@PostMapping(value = "upload", produces="text/html; charset=UTF-8")
@ResponseBody // viewResolver 타지마
public String upload(@ModelAttribute UserImageDTO userImageDTO,
@RequestParam MultipartFile[] img,
HttpSession session) {
// 가상 폴더(/user/storage)
String filePath_lier="D:/Spring/workspace/chapter06_Web/src/main/webapp/WEB-INF/storage";
// 실제 폴더
String filePath = session.getServletContext().getRealPath("/WEB-INF/storage");
System.out.println("실제 폴더 =" + filePath);
String fileName;
File file;
String result ="";
if(img[0] != null) {
fileName = img[0].getOriginalFilename();
file = new File(filePath, fileName);
// img[0].transferTo(file); try-catch문
try {
img[0].transferTo(file);
} catch (IOException e) {
e.printStackTrace();
}
result = "<span><img src='/chapter06_Web/storage/" + fileName + "' width='300' height='300'/></span>";
}
if(img[1] != null) {
fileName = img[1].getOriginalFilename();
file = new File(filePath, fileName);
// img[1].transferTo(file); try-catch문
try {
img[1].transferTo(file);
} catch (IOException e) {
e.printStackTrace();
}
result += "<span><img src='/chapter06_Web/storage/" + fileName + "' width='300' height='300'/></span>";
}
return result;
}
}
<!-- 한번에 여러개의 파일 선택 -->
<tr>
<td colspan="2">
<input type="file" name="img[]" multiple="multiple">
</td>
</tr>
// ----------------- 한번에 여러개의 파일을 선택 -----------------
@PostMapping(value = "upload", produces="text/html; charset=UTF-8")
@ResponseBody // viewResolver 타지마
public String upload(@ModelAttribute UserImageDTO userImageDTO,
@RequestParam("img[]") List<MultipartFile> list,
HttpSession session) {
// 실제 폴더
String filePath = session.getServletContext().getRealPath("/WEB-INF/storage");
System.out.println("실제 폴더 =" + filePath);
String fileName;
File file;
String result ="";
for(MultipartFile img : list) {
fileName = img.getOriginalFilename();
file = new File(filePath, fileName);
try {
img.transferTo(file);
} catch (IOException e) {
e.printStackTrace();
}
result += "<span><img src='/chapter06_Web/storage/" + fileName + "' width='300' height='300'/></span>";
}//for
return result;
}
}
@Controller
@RequestMapping(value = "user")
public class UserControllerUpload {
@Autowired
private UserServiceUpload userServiceUpload;
@GetMapping(value = "uploadForm")
public String uploadForm() {
return "/user/uploadForm";
}
// ----------------- 한번에 여러개의 파일을 선택 -----------------
@PostMapping(value = "upload", produces="text/html; charset=UTF-8")
@ResponseBody // viewResolver 타지마
public String upload(@ModelAttribute UserImageDTO userImageDTO,
@RequestParam("img[]") List<MultipartFile> list,
HttpSession session) {
// 실제 폴더
String filePath = session.getServletContext().getRealPath("/WEB-INF/storage");
System.out.println("실제 폴더 =" + filePath);
String fileName;
File file;
String result ="";
// 파일명만 모아서 DB로 보내기
List<String> fileNameList = new ArrayList<String>();
for(MultipartFile img : list) {
fileName = img.getOriginalFilename();
file = new File(filePath, fileName);
fileNameList.add(fileName);
try {
img.transferTo(file);
} catch (IOException e) {
e.printStackTrace();
}
result += "<span><img src='/chapter06_Web/storage/" + fileName + "' width='300' height='300'/></span>";
}//for
// DB
userServiceUpload.upload(userImageDTO, fileNameList);
return result;
}
}
package user.service;
import java.util.List;
import user.bean.UserImageDTO;
public interface UserServiceUpload {
public void upload(UserImageDTO userImageDTO, List<String> fileNameList);
}
package user.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import user.bean.UserImageDTO;
import user.dao.UserDAOUpload;
@Service
public class UserServiceUploadImpl implements UserServiceUpload {
@Autowired
private UserDAOUpload userDAOUpload;
@Override
public void upload(UserImageDTO userImageDTO, List<String> fileNameList) {
userDAOUpload.upload(userImageDTO, fileNameList);
}
}
package user.dao;
import java.util.List;
import user.bean.UserImageDTO;
public interface UserDAOUpload {
public void upload(UserImageDTO userImageDTO, List<String> fileNameList);
}
package user.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import user.bean.UserImageDTO;
@Repository
@Transactional
public class UserDAOUploadMybatis implements UserDAOUpload{
@Autowired
private SqlSession sqlSession;
@Override
public void upload(UserImageDTO userImageDTO, List<String> fileNameList) {
for(String fileName : fileNameList) {
userImageDTO.setImage1(fileName);
sqlSession.insert("userUploadSQL.upload",userImageDTO);
}//for
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="userUploadSQL">
<insert id="upload" parameterType="user.bean.UserImageDTO">
insert into userimage values(seq_userimage.nextval, #{imageName}, #{imageContent}, #{image1})
</insert>
</mapper>
@Autowired
private ApplicationContext applicationContext;
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource());
sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("spring/mybatis-config.xml"));
//sqlSessionFactoryBean.setMapperLocations(new ClassPathResource("user/dao/userMapper.xml"));
/*
sqlSessionFactoryBean.setMapperLocations(
new ClassPathResource("user/dao/userMapper.xml"),
new ClassPathResource("user/dao/userUploadMapper.xml"));
*/
sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:*/dao/*Mapper.xml"));
return sqlSessionFactoryBean.getObject();
}
# Oracle
create table usertable(
name varchar2(30) not null,
id varchar2(30) primary key,
pwd varchar2(30) not null);
# MySQL
create table usertable(
name varchar(30) not null,
id varchar(30) primary key,
pwd varchar(30) not null);
# Oracle
create table USERIMAGE(
seq number primary key,
IMAGENAME varchar2(50) not null,
IMAGECONTENT varchar2(4000),
IMAGE1 varchar2(200));
create sequence SEQ_USERIMAGE nocycle nocache;
# MySQL
create table USERIMAGE(
seq int(10) primary key auto_increment,
IMAGENAME varchar(50) not null,
IMAGECONTENT varchar(4000),
IMAGE1 varchar(200));
<p><a href="/chapter06_Web/user/uploadForm_AJax">파일업로드_AJax</a></p>
package user.controller;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
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.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import user.bean.UserImageDTO;
import user.service.UserServiceUpload;
@Controller
@RequestMapping(value = "user")
public class UserControllerUploadAJax {
@Autowired
private UserServiceUpload userServiceUpload;
@GetMapping(value = "uploadForm_AJax")
public String uploadForm_AJax() {
return "/user/uploadForm_AJax";
}
// ----------------- 한번에 여러개의 파일을 선택 -----------------
@PostMapping(value = "upload_AJax", produces="text/html; charset=UTF-8")
@ResponseBody // viewResolver 타지마
public String upload(@ModelAttribute UserImageDTO userImageDTO,
@RequestParam("img[]") List<MultipartFile> list,
HttpSession session) {
// 실제 폴더
String filePath = session.getServletContext().getRealPath("/WEB-INF/storage");
System.out.println("실제 폴더 =" + filePath);
String fileName;
File file;
String result ="";
// 파일명만 모아서 DB로 보내기
List<String> fileNameList = new ArrayList<String>();
for(MultipartFile img : list) {
fileName = img.getOriginalFilename();
file = new File(filePath, fileName);
fileNameList.add(fileName);
try {
img.transferTo(file);
} catch (IOException e) {
e.printStackTrace();
}
result += "<span><img src='/chapter06_Web/storage/" + fileName + "' width='300' height='300'/></span>";
}//for
// DB
userServiceUpload.upload(userImageDTO, fileNameList);
return result;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
table {
border-collapse: collapse;
}
th, td {
padding: 5px;
}
</style>
</head>
<body>
<form id="uploadForm"><!-- AJax 이용할 거라서 action 뺐음 $.ajax ~다 써줄거라서 enctype="multipart/form-data" method="post"뺌~-->
<table border="1">
<tr>
<th>상품명</th>
<td><input type="text" name="imageName" size="35">
</td>
</tr>
<tr>
<td colspan="2">
<textarea name="imageContent" rows="10" cols="50"></textarea>
</td>
</tr>
<!-- 한번에 여러개의 파일 선택 -->
<tr>
<td colspan="2">
<span id="showImg"></span>
<img id="camera" alt="카메라" src="../image/camera.png" width="50" height="50">
<input type="file" name="img[]" id="img" multiple="multiple" style="visibility: hidden;">
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="button" value="이미지 업로드" id="uploadBtn">
<input type="reset" value="취소">
</td>
</tr>
</table>
</form>
<script src="http://code.jquery.com/jquery-3.7.0.min.js"></script>
<script type="text/javascript" src="../js/upload_AJax.js"></script>
<script type="text/javascript">
$('#camera').click(function() {
// 강제 이벤트 발생 - trigger
$('#img').trigger('click');
})
</script>
</body>
</html>
$(function(){
$('#uploadBtn').click(function(){
var formData = new FormData($('#uploadForm')[0]);
$.ajax({
type: 'post',
url: '/chapter06_Web/user/upload_AJax',
enctype: 'multipart/form-data',
processData: false,
contentType: false,
data: formData,
success: function(data){
alert(data);
$('#showImg').html(data);
},
error: function(e){
console.log(e);
}
});
});
});
processData
contentType
카메라 사진 눌렀을때 파일 선택과 같은 효과 발생
------------uploadForm_AJax------------
</table>
<br>
<div id="resultDiv"></div>
------------upload_AJax.js------------
success: function(data){
alert(data);
$('#resultDiv').html(data);
},
------------uploadForm_AJax------------추가
<!-- 한번에 여러개의 파일 선택 -->
<tr>
<td colspan="2">
<!-- 업로드 버튼을 누르기 전에 선택한 이미지가 맞는지 확인하기 위해서 이미지를 보여준다. -->
<img id="showImg" width="70" height="70">
<img id="camera" alt="카메라" src="../image/camera.png" width="50" height="50">
<input type="file" name="img[]" id="img" multiple="multiple" style="visibility: hidden;">
</td>
</tr>
<script type="text/javascript">
$('#camera').click(function() {
// 강제 이벤트 발생 - trigger
$('#img').trigger('click');
});
<!-- 업로드 버튼을 누르기 전에 선택한 이미지가 맞는지 확인하기 위해서 이미지를 보여준다. -->
$('#img').change(function() {
readURL(this);
});
function readURL(input){
var reader = new FileReader();
reader.onload = function(e){
$('#showImg').attr('src', e.target.result); // e.target - 이벤트가 발생하는 요소를 반환해준다.
}
reader.readAsDataURL(input.files[0]);
}
</script>
FileReader는 type이 file인 input 태그 또는 API 요청과 같은 인터페이스를 통해 File 또는 Blob 객체를 편리하게 처리할수있는 방법을 제공하는 객체이며 abort, load, error와 같은 이벤트에서 발생한 프로세스를 처리하는데 주로 사용되며, File 또는 Blob 객체를 읽어서 result 속성에 저장한다.
FileReader도 비동기로 동작한다.
FileReader.onload()
load 이벤트의 핸들러. 이 이벤트는 읽기 동작이 성공적으로 완료되었을 때마다 발생한다.