관리 메뉴

거니의 velog

231204_SPRING 2 (9-1) 본문

대덕인재개발원_웹기반 애플리케이션

231204_SPRING 2 (9-1)

Unlimited00 2023. 12. 4. 08:22

package kr.or.ddit.controller.file.item03;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/item3")
public class FileUploadController03 {

	/*
	 * 		4. 비동기 방식 업로드
	 * 
	 * 			- 비동기 방식으로 여러 개의 이미지를 업로드 하는 파일 업로드 기능을 구현한다.
	 * 
	 * 			# 환경설정
	 * 
	 * 				- 의존 관계 정의(pom.xml 설정)
	 * 					> commons-io		: 파일을 처리하기 위한 의존 라이브러리
	 * 					> imgsalr-lib		: 이미지 변환을 처리하기 위한 의존 라이브러리
	 * 					> jackson-databind	: json 데이터 바인딩을 위한 의존 라이브러리
	 * 
	 * 			# 파일 업로드 구현 설명
	 * 
	 * 				- 파일 업로드 등록 화면 컨트롤러 만들기 (FileUploadController03)
	 * 				- 파일 업로드 등록 화면 컨트롤러 메소드 만들기 (item3RegisterForm:get)
	 * 				- 파일 업로드 등록 화면 만들기 (item3/register.jsp)
	 * 				- 여기까지 확인
	 */
	
	@RequestMapping(value = "/register", method = RequestMethod.GET)
	public String item3RegisterForm() {
		return "item3/register";
	}
	
}

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>ITEM3</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		<h2>REGISTER</h2>
		<form action="/item3/register" method="post" id="item" name="item" enctype="multipart/form-data">
			<table border="1">
				<tr>
					<td>상품명</td>
					<td><input type="text" id="itemName" name="itemName" /></td>
				</tr>
				<tr>
					<td>가격</td>
					<td><input type="text" id="price" name="price" /></td>
				</tr>
				<tr>
					<td>파일</td>
					<td>
						<input type="file" id="inputFile" />
						<div class="uploadedList"></div>
					</td>
				</tr>
				<tr>
					<td>개요</td>
					<td><textarea rows="10" cols="30" id="description" name="description" wrap="soft"></textarea></td>
				</tr>
			</table>
			<div>
				<button type="submit" id="registerBtn">Register</button>
				<button type="button" id="listBtn">List</button>
			</div>
		</form>
	</body>
</html>

- http://localhost/item3/register


[pom.xml]

		<!-- 이미지 변환을 처리하기 위한 의존 라이브러리 -->
		<dependency>
			<groupId>org.imgscalr</groupId>
			<artifactId>imgscalr-lib</artifactId>
			<version>4.2</version>
		</dependency>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>ITEM3</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		<h2>REGISTER</h2>
		<form action="/item3/register" method="post" id="item" name="item" enctype="multipart/form-data">
			<table border="1">
				<tr>
					<td>상품명</td>
					<td><input type="text" id="itemName" name="itemName" /></td>
				</tr>
				<tr>
					<td>가격</td>
					<td><input type="text" id="price" name="price" /></td>
				</tr>
				<tr>
					<td>파일</td>
					<td>
						<input type="file" id="inputFile" />
						<div class="uploadedList"></div>
					</td>
				</tr>
				<tr>
					<td>개요</td>
					<td><textarea rows="10" cols="30" id="description" name="description" wrap="soft"></textarea></td>
				</tr>
			</table>
			<div>
				<button type="submit" id="registerBtn">Register</button>
				<button type="button" id="listBtn">List</button>
			</div>
		</form>
	</body>
	<script type="text/javascript">
		$(function(){
			var item = $("#item");					// 폼 태그 Element
			var inputFile = $("#inputFile");	// inputFile Element
			var listBtn = $("#listBtn");			// list 버튼 Element
			
			// 목록 버튼 클릭 시, 목록 화면으로 이동
			listBtn.on("click", function(){
				location.href = "/item3/list";
			});
			
			// Open 파일을 변경했을 때 이벤트 발동
			inputFile.on("change", function(event){
				console.log("change...!");
				
				var files = event.target.files;
				var file = files[0];
				
				console.log(file);
				var formData = new FormData();
				formData.append("file", file);
				
				$.ajax({
					type: "post",
					url: "/item3/uploadAjax",
					data: formData,
					processData: false,
					contentType: false,
					success: function(data){
						console.log(data); // 넘어온 결과를 테스트로 출력
					}
				});
			});
		});
	</script>
</html>

package kr.or.ddit.controller.file.item03;

import java.awt.image.BufferedImage;
import java.io.File;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.UUID;

import javax.imageio.ImageIO;

import org.imgscalr.Scalr;
import org.springframework.util.FileCopyUtils;

public class UploadFileUtils {

	public static String uploadFile(String uploadPath, String originalName, byte[] fileData) throws Exception {
		// UUID 생성
		UUID uuid = UUID.randomUUID();
		
		// UUID_원본파일명
		String savedName = uuid.toString() + "_" + originalName;
		
		// 2023/12/04 폴더 경로를 만들고, /2023/12/04 폴더 경로를 리턴한다.
		String savedPath = calcPath(uploadPath);
		
		// 배포된 서버 업로드 경로 + /2023/12/04 + UUID_원본파일명으로 File target을 하나 만들어 준다.
		File target = new File(uploadPath + savedPath, savedName);
		FileCopyUtils.copy(fileData, target); // 위에서 만들어진 경로와 파일명을 가지고 파일 복사를 진행한다.
		
		String formatName = originalName.substring(originalName.lastIndexOf(".") + 1); // 확장자 추출
		
		// \2023\12\04 경로를 '/' 경로로 변경 후 원본 파일명을 붙인다.
		String uploadedFileName = savedPath.replace(File.separatorChar, '/') + "/" + savedName;
		
		// 확장자가 이미지 파일이면 s_가 붙은 파일의 썸내일 이미지 파일을 생성한다.
		if(MediaUtils.getMediaType(formatName) != null) { // 확장자를 통한 이미지 파일인지 검증
			makeThumbnail(uploadPath, savedPath, savedName); // 썸네일 이미지 생성
		}
		
		return uploadedFileName;
	}
	
	// 썸네일 이미지 만들기
	private static void makeThumbnail(String uploadPath, String path, String fileName) throws Exception {
		// 썸네일 이미지를 만들기 위해 원본 이미지를 읽는다.
		BufferedImage sourceImg = ImageIO.read(new File(uploadPath + path, fileName));
		
		// 썸네일 이미지를 만들기 위한 설정
		// Method.AUTOMATIC : 최소 시간 내에 가장 잘 보이는 이미지를 얻기 위한 사용 방식
		// Mode.FIT_TO_HEIGHT : 이미지 방향과 상관 없이 주어진 높이 내에서 가장 잘 맞는 이미지로 계산
		// targetSize : 값 100, 정사각현 사이즈로 100*100
		BufferedImage destImg = Scalr.resize(sourceImg, Scalr.Method.AUTOMATIC, Scalr.Mode.FIT_TO_HEIGHT, 100);
		
		// 업로드 한 원본 이미지를 가지고 's_'를 붙여서 임시 파일로 만들기 위해 썸네일 경로+파일명을 작성한다.
		String thumbnailName = uploadPath + path + File.separator + "s_" + fileName;
		
		File newFile = new File(thumbnailName);
		String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
		
		// 's_'가 붙은 썸네일 이미지를 만든다.
		ImageIO.write(destImg, formatName.toUpperCase(), newFile);
	}

	// /2023/12/04 경로 생성
	private static String calcPath(String uploadPath) {
		Calendar cal = Calendar.getInstance();
		String yearPath = File.separator + cal.get(Calendar.YEAR); // 2023
		
		// DecimalFormat("00") :: 두자리에서 빈자리는 0으로 채움
		String monthPath = yearPath + File.separator + new DecimalFormat("00").format(cal.get(Calendar.MONTH) + 1); // /2023/12
		String datePath = monthPath + File.separator + new DecimalFormat("00").format(cal.get(Calendar.DATE)); // /2023/12/04
		
		// 년월일 폴더 구조에 의한 폴더 생성
		makeDir(uploadPath, yearPath, monthPath, datePath);
		return datePath;
	}
	
	// 가변 인자
	// 키워드 '...'를 사용한다.
	// [사용법] 타입 ... 변수명 형태로 사용
	// 순서대로 yearPath, monthPath, datePath가 배열로 들어가 처리
	private static void makeDir(String uploadPath, String ...paths) {
		// /2023/12/04 폴더 구조가 존재한다면 return
		// 만들려던 폴더 구조가 이미 만들어져 있는 형태니까 return
		if(new File(paths[paths.length - 1]).exists()) {
			return;
		}
		
		for (String path : paths) {
			File dirPath = new File(uploadPath + path);
			
			// /2023/12/04와 같은 경로에 각 폴더가 없으면 각각 만들어준다.
			if(!dirPath.exists()) {
				dirPath.mkdirs();
			}
		}
	}
	
}

package kr.or.ddit.controller.file.item03;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.MediaType;

public class MediaUtils {

	private static Map<String, MediaType> mediaMap;
	
	// static 그룹 선언
	static {
		mediaMap = new HashMap<String, MediaType>();
		mediaMap.put("JPG", MediaType.IMAGE_JPEG);
		mediaMap.put("GIF", MediaType.IMAGE_GIF);
		mediaMap.put("PNG", MediaType.IMAGE_PNG);
	}
	
	// 넘겨받은 확장자가 포함되어 있는 MediaType이 존재한다면 null이 아니므로 참
	public static MediaType getMediaType(String type) {
		return mediaMap.get(type.toUpperCase());
	}
	
}
package kr.or.ddit.controller.file.item03;

import java.io.IOException;

import javax.annotation.Resource;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
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 lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/item3")
public class FileUploadController03 {

	/*
	 * 		4. 비동기 방식 업로드
	 * 
	 * 			- 비동기 방식으로 여러 개의 이미지를 업로드 하는 파일 업로드 기능을 구현한다.
	 * 
	 * 			# 환경설정
	 * 
	 * 				- 의존 관계 정의(pom.xml 설정)
	 * 					> commons-io		: 파일을 처리하기 위한 의존 라이브러리
	 * 					> imgsalr-lib		: 이미지 변환을 처리하기 위한 의존 라이브러리
	 * 					> jackson-databind	: json 데이터 바인딩을 위한 의존 라이브러리
	 * 
	 * 			# 파일 업로드 구현 설명
	 * 
	 * 				- 파일 업로드 등록 화면 컨트롤러 만들기 (FileUploadController03)
	 * 				- 파일 업로드 등록 화면 컨트롤러 메소드 만들기 (item3RegisterForm:get)
	 * 				- 파일 업로드 등록 화면 만들기 (item3/register.jsp)
	 * 				- 여기까지 확인
	 */
	
	// root-context.xml에서 설정한 uploadPath 빈등록 path 경로를 사용한다.
	@Resource(name = "uploadPath")
	private String resourcePath;
	
	@RequestMapping(value = "/register", method = RequestMethod.GET)
	public String item3RegisterForm() {
		return "item3/register";
	}
	
	@ResponseBody
	@RequestMapping(value = "/uploadAjax", method = RequestMethod.POST, produces = "text/plain; charset=utf-8")
	public ResponseEntity<String> uploadAjax(MultipartFile file) throws Exception {
		log.info("originalName : " + file.getOriginalFilename());
		
		// savesName은 /2023/12/04/UUID_원본파일명을 리턴한다.
		String savesName = UploadFileUtils.uploadFile(resourcePath, file.getOriginalFilename(), file.getBytes());
		return new ResponseEntity<String>(savesName, HttpStatus.OK);
	}
	
}

- http://localhost/item3/register


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>ITEM3</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		<h2>REGISTER</h2>
		<form action="/item3/register" method="post" id="item" name="item" enctype="multipart/form-data">
			<table border="1">
				<tr>
					<td>상품명</td>
					<td><input type="text" id="itemName" name="itemName" /></td>
				</tr>
				<tr>
					<td>가격</td>
					<td><input type="text" id="price" name="price" /></td>
				</tr>
				<tr>
					<td>파일</td>
					<td>
						<input type="file" id="inputFile" />
						<div class="uploadedList"></div>
					</td>
				</tr>
				<tr>
					<td>개요</td>
					<td><textarea rows="10" cols="30" id="description" name="description" wrap="soft"></textarea></td>
				</tr>
			</table>
			<div>
				<button type="submit" id="registerBtn">Register</button>
				<button type="button" id="listBtn">List</button>
			</div>
		</form>
	</body>
	<script type="text/javascript">
		$(function(){
			var item = $("#item");					// 폼 태그 Element
			var inputFile = $("#inputFile");	// inputFile Element
			var listBtn = $("#listBtn");			// list 버튼 Element
			
			// 목록 버튼 클릭 시, 목록 화면으로 이동
			listBtn.on("click", function(){
				location.href = "/item3/list";
			});
			
			// Open 파일을 변경했을 때 이벤트 발동
			inputFile.on("change", function(event){
				console.log("change...!");
				
				var files = event.target.files;
				var file = files[0];
				
				console.log(file);
				var formData = new FormData();
				formData.append("file", file);
				
				$.ajax({
					type: "post",
					url: "/item3/uploadAjax",
					data: formData,
					processData: false,
					contentType: false,
					success: function(data){
						console.log(data); // 넘어온 결과를 테스트로 출력
						
						var str = "";
						
						if(checkImageType(data)) { // 이미지면 이미지 태그를 이용하여 출력
							str += "<div>";
							str += "	<a href='/item3/displayFile?fileName=" + data + "'>";
							str += "		<img src='/item3/displayFile?fileName=" + getThumbnailName(data) + "' />";
							str += "	</a>";
							str += "	<span>X</span>";
							str += "</div>";
						}else { // 파일이면 파일명에 대한 링크로만 출력
							str += "<div>";
							str += "	<a href='/item3/displayFile?fileName=" + data + "'>" + getOriginalName(data) + "</a>";
							str += "	<span>X</span>";
							str += "</div>";
						}
						
						$(".uploadedList").append(str);
					}
				});
			});
			
			// 업로드한 파일이 추가된 div 영역 안에 'X'를 눌러 삭제하면 div 그룹이 통째로 날아간다.
			$(".uploadedList").on("click", "span", function(){
				$(this).parent("div").remove();
			});
			
			item.submit(function(event){
				// form 태그의 submit 이벤트를 우선 block
				event.preventDefault();
				
				var that = $(this); // 현재 발생한 form 태그
				var str = "";
				$(".uploadedList a").each(function(index){
					var value = $(this).attr("href");
					value = value.substr(28); // ?fileName= 다음에 나오는 값
							
					str += "<input type='hidden' name='files["+index+"]' value='"+value+"' />";
				});
				
				console.log("str : " + str);
				that.append(str);
				// form 의 첫뻔재를 가져와서 submit() 처리
				// get() 함수는 여러개 중에 1개를 찾을 때 (form태그가 1개이긴 하지만 여러개 중에 1개를 찾을 때도 활용함)
				that.get(0).submit();
			});
			
			// 임시 파일로 썸네일 이미지 만들기
			function getThumbnailName(fileName) {
				var front = fileName.substr(0,12); // 2023/12/04 폴더 경로
				var end = fileName.substr(12); // 뒤 파일명
				
				console.log("front : " + front);
				console.log("end : " + end);
				
				return front + "s_" + end;
			}
			
			// 파일명 추출(원본 파일명)
			function getOriginalName(fileName) {
				if(checkImageType(fileName)){ // 이미지 파일일 때 리턴
					return;
				}
				
				var idx = fileName.indexOf("_") + 1;
				return fileName.substr(idx);
			}
			
			// 이미지 파일인지 검증
			function checkImageType(fileName) {
				var pattern = /jpg|gif|png|jpeg/i;
				return fileName.match(pattern); // 패턴과 일치하면 true(너 이미지구나?)
			}
			
		});
	</script>
</html>
package kr.or.ddit.controller.file.item03;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.annotation.Resource;

import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
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 lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/item3")
public class FileUploadController03 {

	/*
	 * 		4. 비동기 방식 업로드
	 * 
	 * 			- 비동기 방식으로 여러 개의 이미지를 업로드 하는 파일 업로드 기능을 구현한다.
	 * 
	 * 			# 환경설정
	 * 
	 * 				- 의존 관계 정의(pom.xml 설정)
	 * 					> commons-io		: 파일을 처리하기 위한 의존 라이브러리
	 * 					> imgsalr-lib		: 이미지 변환을 처리하기 위한 의존 라이브러리
	 * 					> jackson-databind	: json 데이터 바인딩을 위한 의존 라이브러리
	 * 
	 * 			# 파일 업로드 구현 설명
	 * 
	 * 				- 파일 업로드 등록 화면 컨트롤러 만들기 (FileUploadController03)
	 * 				- 파일 업로드 등록 화면 컨트롤러 메소드 만들기 (item3RegisterForm:get)
	 * 				- 파일 업로드 등록 화면 만들기 (item3/register.jsp)
	 * 				- 여기까지 확인
	 */
	
	// root-context.xml에서 설정한 uploadPath 빈등록 path 경로를 사용한다.
	@Resource(name = "uploadPath")
	private String resourcePath;
	
	@RequestMapping(value = "/register", method = RequestMethod.GET)
	public String item3RegisterForm() {
		return "item3/register";
	}
	
	@ResponseBody
	@RequestMapping(value = "/uploadAjax", method = RequestMethod.POST, produces = "text/plain; charset=utf-8")
	public ResponseEntity<String> uploadAjax(MultipartFile file) throws Exception {
		log.info("originalName : " + file.getOriginalFilename());
		
		// savesName은 /2023/12/04/UUID_원본파일명을 리턴한다.
		String savesName = UploadFileUtils.uploadFile(resourcePath, file.getOriginalFilename(), file.getBytes());
		return new ResponseEntity<String>(savesName, HttpStatus.OK);
	}
	
	@RequestMapping(value = "/displayFile", method = RequestMethod.GET)
	public ResponseEntity<byte[]> display(String fileName) throws Exception{
		InputStream in = null;
		ResponseEntity<byte[]> entity = null;
		
		log.info("fileName : " + fileName);
		
		try {
			String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
			MediaType mType = MediaUtils.getMediaType(formatName);
			HttpHeaders headers = new HttpHeaders();
			in = new FileInputStream(resourcePath + fileName);
			
			if(mType != null) { // 이미지 파일일 때
				headers.setContentType(mType);
			}else {// 이미지 파일이 아닐 때
				fileName = fileName.substring(fileName.indexOf("_") + 1);
				headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
				headers.add("Content-Disposition", "attachment; filename=\"" + 
						new String(fileName.getBytes("UTF-8"), "ISO-8859-1") + "\"");
			}
			entity = new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED);
		} catch (Exception e) {
			e.printStackTrace();
			entity = new ResponseEntity<byte[]>(HttpStatus.BAD_REQUEST);
		} finally {
			in.close();
		}
		return entity;
	}
	
}

- http://localhost/item3/register

 

이미지 없애면 삭제됨


package kr.or.ddit.vo;

import lombok.Data;

@Data
public class Item3 {

	private int itemId;
	private String itemName;
	private int price;
	private String description;
	private String[] files;
	
}
package kr.or.ddit.controller.file.item03;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.annotation.Resource;
import javax.inject.Inject;

import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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 kr.or.ddit.service.IItemService3;
import kr.or.ddit.vo.Item3;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/item3")
public class FileUploadController03 {

	/*
	 * 		4. 비동기 방식 업로드
	 * 
	 * 			- 비동기 방식으로 여러 개의 이미지를 업로드 하는 파일 업로드 기능을 구현한다.
	 * 
	 * 			# 환경설정
	 * 
	 * 				- 의존 관계 정의(pom.xml 설정)
	 * 					> commons-io		: 파일을 처리하기 위한 의존 라이브러리
	 * 					> imgsalr-lib		: 이미지 변환을 처리하기 위한 의존 라이브러리
	 * 					> jackson-databind	: json 데이터 바인딩을 위한 의존 라이브러리
	 * 
	 * 			# 파일 업로드 구현 설명
	 * 
	 * 				- 파일 업로드 등록 화면 컨트롤러 만들기 (FileUploadController03)
	 * 				- 파일 업로드 등록 화면 컨트롤러 메소드 만들기 (item3RegisterForm:get)
	 * 				- 파일 업로드 등록 화면 만들기 (item3/register.jsp)
	 * 				- 여기까지 확인
	 */
	
	// root-context.xml에서 설정한 uploadPath 빈등록 path 경로를 사용한다.
	@Resource(name = "uploadPath")
	private String resourcePath;
	
	@Inject
	private IItemService3 itemService;
	
	@RequestMapping(value = "/register", method = RequestMethod.GET)
	public String item3RegisterForm() {
		return "item3/register";
	}
	
	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public String item3Register(Item3 item, Model model) {
		String[] files = item.getFiles();
		
		for(int i = 0; i < files.length; i++) {
			log.info("files["+i+"] : " + files[i]);
		}
		itemService.register(item);
		model.addAttribute("msg", "등록이 완료되었습니다.");
		return "item3/success";
	}
	
	@ResponseBody
	@RequestMapping(value = "/uploadAjax", method = RequestMethod.POST, produces = "text/plain; charset=utf-8")
	public ResponseEntity<String> uploadAjax(MultipartFile file) throws Exception {
		log.info("originalName : " + file.getOriginalFilename());
		
		// savesName은 /2023/12/04/UUID_원본파일명을 리턴한다.
		String savesName = UploadFileUtils.uploadFile(resourcePath, file.getOriginalFilename(), file.getBytes());
		return new ResponseEntity<String>(savesName, HttpStatus.OK);
	}
	
	@RequestMapping(value = "/displayFile", method = RequestMethod.GET)
	public ResponseEntity<byte[]> display(String fileName) throws Exception{
		InputStream in = null;
		ResponseEntity<byte[]> entity = null;
		
		log.info("fileName : " + fileName);
		
		try {
			String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
			MediaType mType = MediaUtils.getMediaType(formatName);
			HttpHeaders headers = new HttpHeaders();
			in = new FileInputStream(resourcePath + fileName);
			
			if(mType != null) { // 이미지 파일일 때
				headers.setContentType(mType);
			}else {// 이미지 파일이 아닐 때
				fileName = fileName.substring(fileName.indexOf("_") + 1);
				headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
				headers.add("Content-Disposition", "attachment; filename=\"" + 
						new String(fileName.getBytes("UTF-8"), "ISO-8859-1") + "\"");
			}
			entity = new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED);
		} catch (Exception e) {
			e.printStackTrace();
			entity = new ResponseEntity<byte[]>(HttpStatus.BAD_REQUEST);
		} finally {
			in.close();
		}
		return entity;
	}
	
}

package kr.or.ddit.service;

import kr.or.ddit.vo.Item3;

public interface IItem3Service {

	public void register(Item3 item);

}
package kr.or.ddit.service.impl;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import kr.or.ddit.mapper.IItem3Mapper;
import kr.or.ddit.service.IItem3Service;
import kr.or.ddit.vo.Item3;

@Service
public class Item3ServiceImpl implements IItem3Service {

	@Inject
	private IItem3Mapper mapper;
	
	@Override
	public void register(Item3 item) {
		// 일반적인 데이터를 Insert
		mapper.create(item);
		
		// 일반적인 데이터를 담고 있는 Item3 데이터 안에 파일 데이터가 들어있는데
		// 넘겨받은 파일 데이터를 파일 테이블에 넣는다.
		String[] files = item.getFiles();
		if(files == null) {
			return;
		}
		
		for(String fileName : files) {
			mapper.addAttach(fileName);
		}
	}

}

package kr.or.ddit.mapper;

import kr.or.ddit.vo.Item3;

public interface IItem3Mapper {

	public void create(Item3 item);
	public void addAttach(String fileName);

}

<?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="kr.or.ddit.mapper.IItem3Mapper">
	
	<insert id="create" parameterType="item3">
		insert into item3 (
			item_id, item_name, price, description
		) values (
			seq_item3.nextval, #{itemName}, #{price}, #{description}
		)
	</insert>
	
	<insert id="addAttach" parameterType="string">
		insert into item3_attach (
			fullname, item_id, regdate
		) values (
			#{filename}, seq_item3.currval, sysdate
		)
	</insert>
	
</mapper>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	
	<!--  
		[마이바티스] 스프링에서 "_"를 사용한 컬럼명 사용 시(BOOK 테이블의 BOOK_ID와 같은 컬럼)
		카멜케이스로 읽어주는 역할(bookId와 같이)
		
		ex) 테이블 컬럼명이 member_id인 경우 jsp 화면 단에서 이 값을 사용시 memberId로 사용할 수 있다.
	-->
	<settings>
		<setting name="mapUnderscoreToCamelCase" value="true"/>
	</settings>
	
	<typeAliases>
		<typeAlias type="kr.or.ddit.vo.Board" alias="board"/>
		<typeAlias type="kr.or.ddit.vo.crud.CrudMember" alias="crudMember"/>
		<typeAlias type="kr.or.ddit.vo.crud.CrudMemberAuth" alias="crudMemberAuth"/>
		
		<typeAlias type="kr.or.ddit.vo.test.TagBoardVO" alias="tagboardVO"/>
		<typeAlias type="kr.or.ddit.vo.test.TagVO" alias="tagVO"/>
		
		<typeAlias type="kr.or.ddit.vo.Item" alias="item"/>
		<typeAlias type="kr.or.ddit.vo.Item2" alias="item2"/>
		<typeAlias type="kr.or.ddit.vo.Item3" alias="item3"/>
		
		<typeAlias type="kr.or.ddit.vo.crud.PaginationInfoVO" alias="pagingVO"/>
		<typeAlias type="kr.or.ddit.vo.crud.NoticeVO" alias="noticeVO"/>
		<typeAlias type="kr.or.ddit.vo.crud.NoticeFileVO" alias="noticefileVO"/>
	</typeAliases>
	
</configuration>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>SUCCESS</title>
	</head>
	<body>
		<h2>${msg }</h2>
		<a href="/item3/list">List</a>
	</body>
</html>

- http://localhost/item3/register


 

'대덕인재개발원_웹기반 애플리케이션' 카테고리의 다른 글

231204_SPRING 2 (9-3)  (0) 2023.12.04
231204_SPRING 2 (9-2)  (0) 2023.12.04
231201_SPRING 2 (과제 1)  (0) 2023.12.01
231201_SPRING 2 (8-2)  (0) 2023.12.01
231201_SPRING 2 (8-1)  (0) 2023.12.01