본문 바로가기

개발 공부/Spring

코드로 배우는 스프링 웹 프로젝트-23. 브라우저에서 썸네일 처리

코드로 배우는 스프링 웹 프로젝트-23. 브라우저에서 썸네일 처리

코드로 배우는 스프링 웹 프로젝트 - 개정판

2019년 7월 10일 인쇄판

 

Part6. 파일 업로드 처리

 

Chapter 23. 브라우저에서 썸네일 처리

.브라우저에서 첨부파일 업로드 결과가 JSON 객체로 반환되었다면 남은 작업은 업로드 후 업로드 초기화, 결과 데이터로 화면에 섬네일이나 파일 이미지를 보여주는 작업이다.

 

23.1 <input file='file'>의 초기화

 

위 태그는 다른 DOM 요소와 다르게 readonly라 안쪽 내용을 수정할 수 없으므로, 별도의 방법으로 초기화시킨다.

 

$(document).ready(function() {
	
	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;
	}
	
	var cloneObj = $(".uploadDiv").clone();
	
	$("#uploadBtn").on("click", function(e){
		var formData = new FormData();
		var inputFile = $("input[name='uploadFile']");
		var files = inputFile[0].files;
		console.log(files);
		
		//add filedate to formdata
		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);
				$(".uploadDiv").html(cloneObj.html());
			}
		});
	});
});

위는 uploadAjax.jsp.

cloneObj를 추가하고 success 시 이를 html에 삽입한다

 

 

23.2 업로드된 이미지 처리

 

23.2.1. 파일 이름 출력

 

uploadAjax.jsp에 함수를 추가해 특정 ul 태그 내에 업로드 파일 이름을 보여주도록 한다.

(showUploadedFile 함수)

 

<%@ 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>
</head>
<body>
<h1>Upload with Ajax</h1>
<div class='uploadDiv'>
	<input type='file' name='uploadFile' multiple>
</div>
<div class="uploadResult">
	<ul>
	
	</ul>
</div>
<button id='uploadBtn'> Upload </button>

<script
  src="https://code.jquery.com/jquery-3.5.1.js"
  integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
  crossorigin="anonymous"></script>

<script>
$(document).ready(function() {
	
	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;
	}
	
	var uploadResult = $(".uploadResult ul");
	function showUploadedFile(uploadResultArr) {
		var str = "";
		$(uploadResultArr).each(function(i, obj) {
			str+= "<li>" + obj.fileName + "</li>";
		});
		uploadResult.append(str);
	}
	
	var cloneObj = $(".uploadDiv").clone();
	
	$("#uploadBtn").on("click", function(e){
		var formData = new FormData();
		var inputFile = $("input[name='uploadFile']");
		var files = inputFile[0].files;
		console.log(files);
		
		//add filedate to formdata
		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());
			}
		});
	});
});
</script>
</form>
</body>
</html>

 

showUploadedFile()은 JSON 데이터를 받아 해당 파일 이름을 추가한다. success시 이 함수를 호출하도록 수정

 

23.2.2 일반 파일의 파일 처리

 

우선 일반 파일이 업로드된 상황에서 첨부파일 아이콘을 보여주도록 수정하자.

 

기존 webapp/resources 밑에 폴더 내용을 그대로 추가하고 img 폴더를 생성한다. 일반 첨부파일의 이미지를 보여줄 attach.png 추가

위와 같이 폴더들도 추가.

 

 

<%@ 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>
</head>
<body>
<style>
	.uploadResult {
		width:100%;
		background-color : gray;
	}
	.uploadResult ul {
		display:flex;
		flex-flow: row;
		justify-contetn: center;
		align-items: center;
	}
	.uploadResult ul li {
		list-style: none;
		padding: 10px;
	}
	.uploadResult ul li img{
		width: 20px;
	}
</style>
<h1>Upload with Ajax</h1>
<div class='uploadDiv'>
	<input type='file' name='uploadFile' multiple>
</div>
<div class="uploadResult">
	<ul>
	
	</ul>
</div>
<button id='uploadBtn'> Upload </button>

<script
  src="https://code.jquery.com/jquery-3.5.1.js"
  integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
  crossorigin="anonymous"></script>

<script>
$(document).ready(function() {
	
	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;
	}
	
	var uploadResult = $(".uploadResult ul");
	function showUploadedFile(uploadResultArr) {
		var str = "";
		$(uploadResultArr).each(function(i, obj) {
			if(!obj.image) {
				str+="<li><img src='/resources/img/attach.png'>" + obj.fileName + "</li>";
			} else {
				str += "<li>"+obj.fileName + "</li>";
			}
		});
		uploadResult.append(str);
	}
	
	var cloneObj = $(".uploadDiv").clone();
	
	$("#uploadBtn").on("click", function(e){
		var formData = new FormData();
		var inputFile = $("input[name='uploadFile']");
		var files = inputFile[0].files;
		console.log(files);
		
		//add filedate to formdata
		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());
			}
		});
	});
});
</script>
</form>
</body>
</html>

 

23.2.3 섬네일 이미지 보여주기

 

섬네일은 서버를 통해 특정 URI를 호출하면 보여줄 수 있도록 처리.

해당 파일의 경로와 uuid가 붙은 파일 이름이 필요하다. GET 방식을 통해 가져올 수 있도록 처리한다.

특정한 URI 뒤에 파일 이름을 추가하면 이미지 파일 데이터를 가져와 img 태그 작성을 통해 처리.

 

 

UploadController에서 섬네일 데이터 전송하기.

 

	
	@GetMapping("/display")
	@ResponseBody
	public ResponseEntity<byte[]> getFile(String fileName) {
		log.info("fileName: " + fileName);
		File file = new File("C:\\upload\\" + fileName);
		log.info("file : " + file);
		ResponseEntity<byte[]> result = null;
		
		try {
			HttpHeaders header = new HttpHeaders();
			header.add("Content-Type",  Files.probeContentType(file.toPath()));
			result = new ResponseEntity<byte[]>(FileCopyUtils.copyToByteArray(file),
					header, HttpStatus.OK);
		}catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}

getFile은 문자열로 파일 경로가 포함된 fileName을 받고 byte로 전송한다. byte로 이미지 파일 데이터를 전송하면 MIME 타입이 파일의 종류에 따라 달라질 수 있는데, 이 부분을 해결하기 위해 probeContentType으로 적절한 MIME 타입 데이터를 헤더에 포함할 수 있다.

uploadFile 밑의 영문 이름의 파일들을 추가하고, 브라우저에 fileName=경로/파일이름.jpg를 호출하는 형태로 테스트할 수 있다.

 

JavaScript 처리

 

showUploadedFile 수정

 

<%@ 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>
</head>
<body>
<style>
	.uploadResult {
		width:100%;
		background-color : gray;
	}
	.uploadResult ul {
		display:flex;
		flex-flow: row;
		justify-contetn: center;
		align-items: center;
	}
	.uploadResult ul li {
		list-style: none;
		padding: 10px;
	}
	.uploadResult ul li img{
		width: 20px;
	}
</style>
<h1>Upload with Ajax</h1>
<div class='uploadDiv'>
	<input type='file' name='uploadFile' multiple>
</div>
<div class="uploadResult">
	<ul>
	
	</ul>
</div>
<button id='uploadBtn'> Upload </button>

<script
  src="https://code.jquery.com/jquery-3.5.1.js"
  integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
  crossorigin="anonymous"></script>

<script>
$(document).ready(function() {
	
	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;
	}
	
	var uploadResult = $(".uploadResult ul");
	function showUploadedFile(uploadResultArr) {
		var str = "";
		$(uploadResultArr).each(function(i, obj) {
			if(!obj.image) {
				str+="<li><img src='/resources/img/attach.png'>" + obj.fileName + "</li>";
			} else {
				//str += "<li>"+obj.fileName + "</li>";
				var fileCallPath = encodeURIComponent(obj.uploadPath + "/s_" 
						+ obj.uuid + "_" + obj.fileName);
				str += "<li><img src='/display?fileName=" + fileCallPath + "'><li>";
			}
		});
		uploadResult.append(str);
	}
	
	var cloneObj = $(".uploadDiv").clone();
	
	$("#uploadBtn").on("click", function(e){
		var formData = new FormData();
		var inputFile = $("input[name='uploadFile']");
		var files = inputFile[0].files;
		console.log(files);
		
		//add filedate to formdata
		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());
			}
		});
	});
});
</script>
</form>
</body>
</html>