본문 바로가기
ICIA 수업일지

2021.10.12 수업일지(Spring 연습, fileupload 방법

by 주성씨 2021. 10. 12.

- Form과 Ajax를 이용한 파일 업로드

1. form을 이용한 파일 업로드

/ex06/pom.xml

.....
<dependency>
 <groupId>commons-fileupload</groupId>
 <artifactId>commons-fileupload</artifactId>
 <version>1.3.1</version>
</dependency>
.....

 

- servlet-context.xml 파일에 아래 내용을 추가한다.

.....
	<!-- 파일 업로드 루트 설정 -->
	<beans:bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<beans:property name="maxUploadSize" value="10485760" />
	</beans:bean>
	<beans:bean id="uploadPath" class="java.lang.String">
		<beans:constructor-arg value="C:/data/upload" /> <<<--- 업로드할 경로 설정
	</beans:bean>
.....

 

- UploadController를 생성한 후 uploadForm 메서드를 작성한다

- /ex06/src/main/java/com/example/controller/UploadController.java

package com.example.controller;

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

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
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;

@Controller
public class UploadController {
	@Resource(name = "uploadPath")
	private String path;

	@RequestMapping("/uploadForm")
	public void uploadFomr() {
	}

	// 파일 업로드
	@RequestMapping(value = "/uploadForm", method = RequestMethod.POST)
	public void uploadFormPost(MultipartFile file) throws Exception { // @RequestParam("file")
																		// MultipartFile[]
																		// files
		// 여러 개의 파일을 업로드 하는 경우 for(MultipartFile file:files){ ... }
		// System.out.println("파일사이즈:" + file.getSize());
		System.out.println("파일타입:" + file.getContentType());
		System.out.println("파일명:" + file.getOriginalFilename());
		UUID uid = UUID.randomUUID();
		String savedName = uid.toString() + "_" + file.getOriginalFilename();
		File target = new File(path, savedName);
		FileCopyUtils.copy(file.getBytes(), target);
	}
.....

 

- uploadForm.jsp 파일을 작성한다. 

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>파일 업로드</title>
</head>
<body>
	<h1>[파일업로드 Form]</h1>
	<form id="frm" action="uploadForm" method="post"
		enctype="multipart/form-data">
		<input type="file" name="file">
		<!-- 여러개의 파일을 선택하는 경우 multiple -->
		<input type="submit" value="저장">
	</form>
</body>
</html>

 

확인

 

 

2. Ajax을 이용한 파일 업로드

/ex06/src/main/java/com/example/controller/UploadController.java

.....
	@RequestMapping("/uploadAjax")
	public void uploadAjax() {
	}

	
	// Ajax으로 업로드
	@RequestMapping(value = "/uploadFile", method = RequestMethod.POST, produces = "text/plain;charset=UTF-8")
	@ResponseBody
	public String uploadAjaxPost(MultipartFile file) throws Exception {
		System.out.println("파일사이즈:" + file.getSize());
		System.out.println("파일타입:" + file.getContentType());
		System.out.println("파일명:" + file.getOriginalFilename());

		UUID uid = UUID.randomUUID();
		String savedName = uid.toString() + "_" + file.getOriginalFilename();
		File target = new File(path, savedName);
		FileCopyUtils.copy(file.getBytes(), target);
		return savedName;
	}
}

 

/ex06/src/main/webapp/WEB-INF/views/uploadAjax.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="http://code.jquery.com/jquery-3.1.1.min.js"></script>
<title>Ajax으로 업로드</title>
</head>
<body>
	<h1>[Ajax 파일 업로드]</h1>
	<div id="upload">
		<input type="file" id="file" />

	</div>
</body>
<script>
	// 파일 변경시 
	$('#file').on("change", function() {
		// 똑같은 파일이 있을 수 있기 때문에 0번째 데이터 하나만 선택할 것이기 때문에
		var file = $("#file")[0].files[0];
		// 파일 없으면 빠져나옴
		if (file == null)
			return;
		// 업로드하고자하는 파일을 formdata에 넣음
		var formData = new FormData();
		formData.append("file", file);
		// ajax으로 넣음
		// 컨트롤러에 포스트하는 작업을 하도록 하겠다.
		$.ajax({
			type : 'post',
			url : "/uploadFile",
			processData : false,
			contentType : false,
			data : formData,
			success : function(data) {
				alert(data);
			}
		})
	});
</script>
</html>

 

 

 

- 파일 업로드 목록을 출력해보도록 하겠다.

/ex06/src/main/webapp/WEB-INF/views/uploadAjax.jsp

.....
<body>
	<h1>[Ajax 파일 업로드]</h1>
	<div id="upload">
		<input type="file" id="file" />
	</div>
	<!-- 파일 업로드 목록 출력 -->
	<div id="uploaded">
		<ul id="uploadedFiles"></ul>
	</div>
</body>
<script>
	// 파일 변경시 
	$('#file').on("change", function() {
		// 똑같은 파일이 있을 수 있기 때문에 0번째 데이터 하나만 선택할 것이기 때문에
		var file = $("#file")[0].files[0];
		// 파일 없으면 빠져나옴
		if (file == null)
			return;
		// 업로드하고자하는 파일을 formdata에 넣음
		var formData = new FormData();
		formData.append("file", file);
		// ajax으로 넣음
		// 컨트롤러에 포스트하는 작업을 하도록 하겠다.
		$.ajax({
			type : 'post',
			url : "/uploadFile",
			processData : false,
			contentType : false,
			data : formData,
			success : function(data) {
				var str ="<li>";
				str += data + "<a href=''>X</a>";
				str += "</li>";
				// 계속 추가할거니 append로 한다.
				$("#uploadedFiles").append(str);
			}
		})
	});
	
	$("#uploadedFiles").on('click',function(e){
		e.preventDefault();
		
	})
</script>
.....

 

확인

 

- 업로드한 파일을 디스크에서 삭제해보겠다.

.....
<script>
	// 파일 변경시 
	$('#file').on("change", function() {
		// 똑같은 파일이 있을 수 있기 때문에 0번째 데이터 하나만 선택할 것이기 때문에
		var file = $("#file")[0].files[0];
		// 파일 없으면 빠져나옴
		if (file == null)
			return;
		// 업로드하고자하는 파일을 formdata에 넣음
		var formData = new FormData();
		formData.append("file", file);
		// ajax으로 넣음
		// 컨트롤러에 포스트하는 작업을 하도록 하겠다.
		$.ajax({
			type : 'post',
			url : "/uploadFile",
			processData : false,
			contentType : false,
			data : formData,
			success : function(data) {
				var str = "<li>";
				str += data + "<a href='"+data+"'>X</a>";
				str += "</li>";
				// 계속 추가할거니 append로 한다.
				$("#uploadedFiles").append(str);
			}
		})
	});

	$("#uploadedFiles").on('click', "li a", function(e) {
		e.preventDefault();
		var li = $(this).parent();
		var fileName = $(this).attr("href");
		if (!confirm(fileName + "을(를) 삭제하시겠습니까?"))
			return;
		$.ajax({
			type : 'post',
			url : "/deleteFile",
			data : {
				"fileName" : fileName
			},
			success : function() {
				alert("삭제성공")
				li.remove();
			}
		})
	})
</script>
.....

 

/ex06/src/main/java/com/example/controller/UploadController.java

.....
	// 2. Ajax 파일 삭제
	@RequestMapping(value="/deleteFile", method=RequestMethod.POST)
	@ResponseBody
	public void deleteFile(String fileName){
		new File(path+"/"+fileName).delete();
	}
.....

 

업로드 및 삭제 확인

 

 

- 이제 게시판을 파일첨부를 포함해서 만들도록 하겠다.

 

- go to mysql

- 업로드할 파일명을 저장할 테이블을 만들겠다.

#2021.10.12 게시판 파일 업로드용 테이블 생성
create table tbl_attach(
    fullname varchar(150) not null, 
    bno int not null, 
    regdate datetime default now(), 
    primary key(fullname), 
    foreign key(bno) references tbl_board(bno)
);

 

확인

 

- BoardVO, ReplyVO 복사해서 해당 프로젝트 domain에 넣는다.

/ex06/src/main/java/com/example/domain/BoardVO.java

.....
	// 파일 추가 여러개로 할것이라서 배열로
	private String[] files;

	public String[] getFiles() {
		return files;
	}

	public void setFiles(String[] files) {
		this.files = files;
	}
.....
	@Override
	public String toString() {
		return "BoardVO [bno=" + bno + ", title=" + title + ", content=" + content + ", writer=" + writer + ", regdate="
				+ regdate + ", updatedate=" + updatedate + ", viewcount=" + viewcount + ", replycount=" + replycount
				+ ", files=" + Arrays.toString(files) + "]";
	}
.....

 

/ex06/src/main/resources/mapper/BoardMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.MysqlMapper">
	<!-- 목록읽기 -->
	<select id="list" resultType="com.example.domain.BoardVO">
		select * from tbl_board
		order by bno desc
		limit 0,10
	</select>
	<!-- 글읽기 -->
	<select id="read" resultType="com.example.domain.BoardVO">
		select * from tbl_board
		where bno=#{bno}
	</select>
	<!-- 삽입 -->
	<insert id="insert">
		insert into tbl_board(title,content,writer)
		values(#{title},#{content},'user01')
	</insert>
	<!-- 업데이트 -->
	<update id="update">
		update tbl_board set title=#{title},content=#{content}
		where bno = #{bno}
	</update>
	<!-- 삭제 -->
	<delete id="delete">
		delete from tbl_board
		where bno=#{bno}
	</delete>
</mapper>

 

- mapper에 새로운 interface를 만들겠다.

/ex06/src/main/java/com/example/mapper/BoardDAO.java

package com.example.mapper;

import java.util.List;

import com.example.domain.BoardVO;

public interface BoardDAO {
	public List<BoardVO> list();

	public void insert(BoardVO vo);

	public void update(BoardVO vo);

	public void delete(int bno);
	
	public BoardVO read(int bno);
}

 

 

- 이제 메서드를 오버라이드할 implement를 만들겠다.

/ex06/src/main/java/com/example/mapper/BoardDAOImpl.java

package com.example.mapper;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.example.domain.BoardVO;

@Repository
public class BoardDAOImpl implements BoardDAO {

	@Autowired
	SqlSession session;

	String namespace = "com.example.mapper.BoardMapper";

	@Override
	public List<BoardVO> list() {
		return session.selectList(namespace + ".list");
	}

	@Override
	public void insert(BoardVO vo) {
		session.insert(namespace + ".insert", vo);
	}

	@Override
	public void update(BoardVO vo) {
		session.update(namespace + ".insert", vo);
	}

	@Override
	public void delete(int bno) {
		session.delete(namespace + ".delete", bno);

	}

	@Override
	public BoardVO read(int bno) {
		return session.selectOne(namespace + ".read", bno);
	}

}

 

/ex06/src/test/java/com/example/controller/MysqlTest.java

package com.example.controller;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.example.mapper.BoardDAOImpl;
import com.example.mapper.MysqlMapper;

@RunWith(SpringJUnit4ClassRunner.class) // 먼저 SpringJUnit4ClassRunner.class
										// import한다.
@ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/spring/**/*.xml"})
public class MysqlTest {
	// 자동으로 연결
	@Autowired
	private BoardDAOImpl mapper;

	// 연결해서 getList을 테스트
	@Test
	public void getList() {
		mapper.list();
	}
}

 

확인

 

- 이제 목록 출력하고 등록하는 페이지를 만들겠다.

/ex06/src/main/java/com/example/controller/BoardController.java

package com.example.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.mapper.BoardDAO;

@Controller
public class BoardController {
	@Autowired
	BoardDAO dao;
	
	@RequestMapping("/list")
	public String list(){
		return "list";
	}
}

// Ajax으로 안할거면 아래
package com.example.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.mapper.BoardDAO;

@Controller
public class BoardController {
	@Autowired
	BoardDAO dao;
	
	@RequestMapping("/list")
	public String list(Model model){
		model.addAttribute("list",dao.list());
		return "list";
	}
}

 

/ex06/src/main/webapp/WEB-INF/views/list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>게시판</title>
</head>
<body>
	<h1>[게시판]</h1>
	<a href="insert">글쓰기</a>
	<c:forEach items="${list}" var="vo">
		<div>
			<span>${vo.bno}:${vo.title}</span>
			<span><b>${vo.regdate}</b></span>
		</div>
	</c:forEach>
</body>
</html>

 

/ex06/src/main/java/com/example/controller/BoardController.java

.....
	//2. insert
	@RequestMapping("/insert")
	public void insert(){
		
	}
.....

 

- 글쓰기 페이지 생성

/ex06/src/main/webapp/WEB-INF/views/insert.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="http://code.jquery.com/jquery-3.1.1.min.js"></script>
<script
	src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.1/handlebars.js"></script>
<title>글쓰기</title>
<style>
form {
	width: 500px;
	padding: 20px;
}

input[type=text] {
	width: 100%;
	margin: 10px;
}

textarea {
	width: 100%;
	margin: 10px;
}
</style>
</head>
<body>
	<h1>[글쓰기]</h1>
	<div>
		<form name="frm" method="post">
			<input type="text" name="title" value="파일 첨부 테스트" />
			<textarea rows="5" cols="50" name="content">파일 첨부 테스트</textarea>
			<hr />
			<input type="submit" value="등록" /> <input type="reset" value="취소" />
			<hr />
			<h3>파일첨부</h3>
			<input type="file" id="file" />
			<ul id="uploadedFiles"></ul>
			<script id="temp" type="text/x-handlebars-template">
				<li>
					{{fileName}}
					<a href="{{fileName}}">삭제</a>
					<input type="text" name="files" value={{fullName}} size=50/>
				</li>
			</script>
		</form>
	</div>
</body>
<script>
	// 파일 변경시 
	$('#file').on("change", function() {
		// 똑같은 파일이 있을 수 있기 때문에 0번째 데이터 하나만 선택할 것이기 때문에
		var file = $("#file")[0].files[0];
		// 파일 없으면 빠져나옴
		if (file == null)
			return;
		// 업로드하고자하는 파일을 formdata에 넣음
		var formData = new FormData();
		formData.append("file", file);
		// ajax으로 넣음
		// 컨트롤러에 포스트하는 작업을 하도록 하겠다.
		$.ajax({
			type : 'post',
			url : "/uploadFile",
			processData : false,
			contentType : false,
			data : formData,
			success : function(data) {
				alert("....................")
				var temp = Handlebars.compile($('#temp').html());
				tempData = {
					"fileName" : data,
					"fullName" : data
				}
				$('#uploadedFiles').append(temp(tempData));
			}
		})
	})

	$("#uploadedFiles").on('click', "li a", function(e) {
		e.preventDefault();
		var li = $(this).parent();
		var fileName = $(this).attr("href");
		if (!confirm(fileName + "을(를) 삭제하시겠습니까?"))
			return;
		$.ajax({
			type : 'post',
			url : "/deleteFile",
			data : {
				"fileName" : fileName
			},
			success : function() {
				alert("삭제성공")
				li.remove();
			}
		})
	})
</script>
</html>

 

- 글 insert를 위한 컨트롤러 생성

/ex06/src/main/java/com/example/controller/BoardController.java

.....
	//2. insert 페이지
	@RequestMapping("/insert")
	public void insert(){
		
	}
	
	//2_1. insert data
	@RequestMapping(value="/insert", method=RequestMethod.POST)
	public String insertPost(BoardVO vo){
		System.out.println(vo.toString());
		dao.insert(vo);
		return "redirect:list";
	}
.....

 

ex06.zip
0.05MB