https://mvnrepository.com/artifact/net.coobird/thumbnailator/0.4.8

페이지 하단 코드 복사 후 pom.xml에 붙여넣기

 

fileUpload 폴더 생성

 

src/main/java 경로에 UploadController 클래스 추가 후 작성

@Controller
@Log4j
public class UploadController {
	
	private String uploadPath
		= "D:\\PDH\\workspace\\sts\\springstudent\\src\\main\\webapp\\resources\\fileUpload";
	
	public void uploadForm() {
		log.info("upload form..........................");
	}
	
	@GetMapping("/uploadAjax")
	public void uploadAjax() {
		log.info("upload ajax..........................");
	}
}

 

view 폴더에 uploadAjax.jsp 파일 생성 후 작성

<%@ 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>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
	$(function() {
		$("#uploadBtn").on("click", function(e) {
			var formData = new FormData();
			var inputFile = $("input[name='uploadFile']");
			var files = inputFile[0].files;
			console.log(files);
		});
	});
</script>
</head>
<body>
	<h1>Upload With Ajax</h1>
	<div class="uploadDiv">
		<input type="file" name="uploadFile" multiple="multiple">
	</div>
	<button id="uploadBtn">Upload</button>
</body>
</html>

 

톰캣 구동 후 주소창에 http://localhost:9090/uploadAjax 입력하여 접속

파일 첨부 후 Upload버튼을 클릭하고 개발자도구에서 콘솔창에 정보가 잘 뜨는지 확인

 

src/main/java경로의 domain 패키지에 AttachFileDTO 클래스 생성 후 작성

@Data
public class AttachFileDTO {
	private String fileName;
	private String uploadPath;
	private String uuid;
	private boolean image;
}

 

UploadController 파일로 돌아와서 메소드 추가

@PostMapping("/uploadFormAction")
public void uploadFormPost(MultipartFile[] uploadFile, Model model) {
    for (MultipartFile multipartFile : uploadFile) {
        log.info("--------------------------");
        log.info("Upload file name : " + multipartFile.getOriginalFilename());
        log.info("Upload file size : " + multipartFile.getSize());
        log.info("Upload file content type : " + multipartFile.getContentType());

        File saveFile = new File(uploadPath, multipartFile.getOriginalFilename());

        try {
            multipartFile.transferTo(saveFile);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }
}

// 년,월,일 폴더 생성
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 {
        String contentType = Files.probeContentType(file.toPath());
        return contentType.startsWith("image");
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

@PostMapping(value = "/uploadAjaxAction", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<List<AttachFileDTO>> uploadAjaxPost(MultipartFile[] uploadFile) {
    log.info("update ajax post.......................");
    List<AttachFileDTO> attachList = new ArrayList<>();

    String uploadFolderPath = getFolder();

    File uploadFolder = new File(uploadPath, getFolder());
    log.info("uploadForder path : " + uploadFolder);

    if(uploadFolder.exists() == false) {
        uploadFolder.mkdirs();
    }

    for (MultipartFile multipartFile : uploadFile) {
        log.info("--------------------------");
        log.info("Upload file name : " + multipartFile.getOriginalFilename());
        log.info("Upload file size : " + multipartFile.getSize());
        log.info("Upload file content type : " + multipartFile.getContentType());

        AttachFileDTO attachFileDTO = new AttachFileDTO();

        String uploadFileName = multipartFile.getOriginalFilename();

        uploadFileName = uploadFileName.substring(uploadFileName.lastIndexOf("\\") + 1);
        log.info("only file name : " + uploadFileName);

        attachFileDTO.setFileName(uploadFileName);

        UUID uuid = UUID.randomUUID();

        uploadFileName = uuid.toString() + "_" + uploadFileName;

        try {
            File saveFile = new File(uploadFolder, uploadFileName);
            multipartFile.transferTo(saveFile);

            attachFileDTO.setUuid(uuid.toString());
            attachFileDTO.setUploadPath(uploadFolderPath);

            if(checkImageType(saveFile)) {
                attachFileDTO.setImage(true);

                File thumbnail = new File(uploadFolder, "s_" + uploadFileName);
                Thumbnails.of(saveFile).size(100, 100).toFile(thumbnail);
            }

            attachList.add(attachFileDTO);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }
    return new ResponseEntity<>(attachList, HttpStatus.OK);
}

@GetMapping("/display")
@ResponseBody
public ResponseEntity<byte[]> getFile(String fileName) {
    log.info("fileName : " + fileName);

    File file = new File(uploadPath + "\\" + 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<>(FileCopyUtils.copyToByteArray(file), header, HttpStatus.OK);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return result;
}

// 파일 다운로드
@GetMapping(value = "/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public ResponseEntity<Resource> downloadFile(@RequestHeader("User-Agent") String userAgent, String fileName) {
    Resource resource = new FileSystemResource(uploadPath + "\\" + fileName);

    if(resource.exists() == false) {
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }

    String resourceName = resource.getFilename();

    String resourceOriginalName = resourceName.substring(resourceName.indexOf("_") + 1);

    HttpHeaders headers = new HttpHeaders();

    try {
        boolean checkIE = (userAgent.indexOf("MSIE") > -1 || userAgent.indexOf("Trident") > -1);

        String downloadName = null;

        if(checkIE) {
            downloadName = URLEncoder.encode(resourceOriginalName, "UTF-8").replaceAll("\\", "");
        } else {
            downloadName = new String(resourceOriginalName.getBytes("UTF-8"), "ISO-8859-1");
        }

        headers.add("Content-Disposition", "attachment; filename=" + downloadName);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}

// 파일 삭제
@PostMapping("/deleteFile")
@ResponseBody
public ResponseEntity<String> deleteFile(String fileName, String type) {
    log.info("deleteFile : " + fileName);

    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-type", "text/html; charset=UTF-8");

    File file;

    try {
        file = new File(uploadPath + "\\" + URLDecoder.decode(fileName, "UTF-8"));

        file.delete();

        if(type.equals("image")) {
            String largeFileName = file.getAbsolutePath().replace("s_", "");
            log.info("largeFileName : " + largeFileName);

            file = new File(largeFileName);

            file.delete();
        }
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }
    return new ResponseEntity<>("deleted", headers, HttpStatus.OK);
}

 

uploadAjax.jsp 파일 수정

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:set var="ctx" value="${pageContext.request.contextPath == '/' ? '': pageContext.request.contextPath }" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
	.uploadResult {
		width: 100%;
		background-color: gray;
	}
	.uploadResult ul {
		display: flex;
		flex-flow : row;
		justify-content: center;
		align-items: center;
	}
	.uploadResult ul li {
		list-style: none;
		padding: 10px;
	}
	.uploadResult ul li img {
		width: 100px;
	}
	.bigPictureWrapper {
		position: absolute;
		display: none;
		justify-content: center;
		align-items: center;
		top: 0;
		width: 100%;
		height: 100%;
		background-color: gray;
		z-index: 100;
	} 
	.bigPicture {
		position: relative;
		display: flex;
		justify-content: center;
		align-items: center;
		
	}
	.bigPicture img {
		width: 600px;
	}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
	function showImage(fileCallPath) {
		$(".bigPictureWrapper").css("display", "flex").show();
		
		$(".bigPicture")
			.html("<img src='${ctx}/display?fileName=" + fileCallPath + "'>" )
			.animate({width: "100%", height: "100%"}, 1000);
	}
	
	$(function() {
		var regex = new RegExp("(.*?)\.(exe|sh|zip|alz)$");
		
		var maxSize = 5242880;
		
		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);
			
			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 : "${ctx}/uploadAjaxAction",
				processData : false,
				contentType : false,
				data : formData,
				type : "POST",
				dataType : "json",
				success : function(result) {
					console.log(result);
					showUploadedFile(result);
					$(".uploadDiv").html(cloneObj.html());
				}
			});
			
			var uploadResult = $(".uploadResult ul");
			
			function showUploadedFile(uploadResultArr) {
				var str = "";
				
				$(uploadResultArr).each(function(i, obj) {
					if (!obj.image) {
						var fileCallPath = encodeURIComponent(obj.uploadPath + "/" + obj.uuid + "_" + obj.fileName);
						var fileLink = fileCallPath.replace(new RegExp(/\\/g), "/");
						
						str += "<li><div><a href='${ctx}/download?fileName=" + fileCallPath + "'>" + "<img src='${ctx}/resources/img/attach.png'>" + obj.fileName + "</a>"
								+ "<span data-file=\'" + fileCallPath + "\' data-type='file'>x</span>"
								+ "</div></li>";
					} else {
						var fileCallPath = encodeURIComponent(obj.uploadPath + "/s_" + obj.uuid + "_" + obj.fileName);
						var originPath = obj.uploadPath + "\\" +  obj.uuid + "_" + obj.fileName;
						
						originPath = originPath.replace(new RegExp(/\\/g), "/");
						
						str += "<li><a href=\"javascript:showImage(\'" + originPath + "\')\">" + "<img src='${ctx}/display?fileName=" + fileCallPath + "'></a>"
								+ "<span data-file=\'" + fileCallPath + "\' data-type='image'>x</span>"
								+ "</li>";
					}
				});
						
				uploadResult.append(str);
			}
			
			$(".bigPictureWrapper").on("click", function(e) {
				$(".bigPicture").animate({width: "0%", height: "0%"}, 1000);
				
				setTimeout(() => {
					$(this).hide();
				}, 1000);
			});
			
			$(".uploadResult").on("click", "span", function(e) {
				var targetFile = $(this).data("file");
				var type = $(this).data("type");
				
				console.log(targetFile);
				
				$.ajax({
					url : "${ctx}/deleteFile",
					data : {fileName: targetFile, type: type},
					dataType : "text",
					type : "POST",
					success : function(result) {
						alert(result);
					}
				});
			});
		});
	});
</script>
</head>
<body>
	<h1>Upload With Ajax</h1>
	<div class="bigPictureWrapper">
		<div class="bigPicture">
		</div>
	</div>
	
	<div class="uploadDiv">
		<input type="file" name="uploadFile" multiple="multiple">
	</div>
	<div class="uploadResult">
		<ul>
		</ul>
	</div>
	<button id="uploadBtn">Upload</button>
</body>
</html>

 

그리고 이미지가 아닌 파일을 업로드 할 때 사용 될 파일첨부 아이콘을 추가

resources 폴더에 img 폴더를 만들고 그 안에 아이콘 넣기

 

톰캣 구동 후 http://localhost:9090/uploadAjax 에 접속해서 잘 등록되는지 확인

 

그리고 만들어둔 fileUpload 폴더에 년/월/일 폴더 생성이 잘 되는지 확인