Spring 파일 업로드2
파일 업로드 2
폼 및 Ajax 파일
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
.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;
}
</style>
<style>
.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;
}
</style>
</head>
<body>
<h1>Upload with Ajax</h1>
<div class="bigPictureWrapper">
<div class="bigPicture"></div>
</div>
<div class="uploadDiv">
<input type="file" name="uploadfile" multiple>
</div>
<!-- 업로드된 파일정보를 출력 -->
<div class="uploadResult">
<ul></ul>
</div>
<button id="uploadBtn">Upload</button>
<script>
// 정규식-문자열을 대상으로 패턴문법을 이용하여, 패턴에 일치되는지 여부를 확인
let regex = new RegExp("(.*?)\.(exe|sh|zip|alz)$");
let maxSize = 5 * 1024 * 1024; //5mb
// 업로드 파일크기, 확장자 체크
function checkExtension(fileName, fileSize){
if(fileName >= maxSize){
alert("파일 크기용량 초과");
return false;
}
if(regex.test(fileName)){
alert("해당 종류의 파일은 업로드 불가");
return false;
}
return true;
}
// cloneObj 안에 class가 uploadDiv인 div 태그 clone
let cloneObj = $(".uploadDiv").clone();
// 업로드 된 파일정보를 출력하는 태그를 참조
let uploadResult = $(".uploadResult ul");
// 파일정보를 출력하는 함수
// uploadResultArr 파라미터 : 파일들에 대한 정보
function showUploadedFile(uploadResultArr){
let str = ""; // 파일정보를 html태그와 함께 구성
$(uploadResultArr).each(function(i,obj){
// private String uuid; // 중복되자 않는 파일명
// private String uploadPath; // 날짜를 이용한 업로드 폴더명
// private String fileName; // 클라이언트에서 보낸 파일명
// private boolean image; // 이미지 파일구분. true -> 이미지, false -> 이미지가 아닌 파일
if(!obj.image) { // 일반파일
let fileCalPath = obj.uploadPath + "/" + obj.uuid + "_" + obj.fileName;
// console.log("일반파일경로 : " + fileCalPath);
// console.log("일반파일경로 : " + encodeURIComponent(fileCalPath));
str += "<li><div><a href='/download?fileName=" + fileCalPath + "'><image src='/resources/img/attach.png'>" +
obj.fileName + "</a><span style='cursor:pointer;' data-file=\'" + fileCalPath + "\' data-type='file'></span></div></li>";
} else { // 이미지파일
let fileCalPath = obj.uploadPath + "/" + "s_" + obj.uuid + "_" + obj.fileName; // 섬네일 이미지 경로
let originPath = obj.uploadPath + "\\" + obj.uuid + "_" + obj.fileName; // 원본이미지 경로
console.log(fileCalPath);
originPath - originPath.replace(new RegExp(/\\/g), "/");
console.log(fileCalPath);
str += "<li><a href=\"javascript:showImage('" + originPath + "')\"><img src='/display?fileName" + fileCalPath + "'></a>" +
"<span style ='cursor:pointer;' data-file=\'" + fileCalPath + "\' data-type='image'></span></li>";
}
});
uploadResult.append(str);
}
$(document).ready(function(){
$("#uploadBtn").on("click", function(){
let formData = new FormData(); // form태그에 해당하는 의미. 데이터를 key:value 형태로 관리
// <input type="file" name="uploadfile"> 아래 선택자가 복수개념
let inputFile = $("input[name='uploadfile']");
// 선택된 파일들의 정보를 참조
let files = inputFile[0].files;
console.log(files);
// 파일크기와 확장자를 체크
for(let i=0; i<files.length; i++){
if(!checkExtension(files[i].name, files[i].size)) {
return false;
}
// uploadFile 는 컨트롤러 메서드의 변수와 같아야 한다
formData.append("uploadFile", files[i]);
}
// ajax 작업
$.ajax({
url: 'uploadAjaxAction',
// 기본값 true. false는 key:value값의 구조를 Query String으로 변환
processData: false,
// 기본값 true. false는 "application/x-www-form-urlencoded;charset=UTF-8" -> "multipart/form-data" 인코딩을 사용하여 전송.
contentType: false,
// 전송데이터. 파일정보
data: formData,
type: 'post',
// 스프링에서 넘어오는 데이터 포맷
dataType: 'json',
success: function(result){
console.log("파일정보 : " + result[0].fileName);
//result 변수의 내용을 참조하여, 화면에 업로드된 파일정보를 출력
showUploadedFile(result);
}
});
});
});
</script>
</body>
</html>
AttachFileDTO 파일
package com.demo.domain;
import lombok.Data;
// 업로드 된 파일정보를 저장목적
@Data
public class AttachFileDTO {
private String uuid; // 중복되자 않는 파일명
private String uploadPath; // 날짜를 이용한 업로드 폴더명
private String fileName; // 클라이언트에서 보낸 파일명
private boolean image; // 이미지 파일구분. true -> 이미지, false -> 이미지가 아닌 파일
}
컨트롤러 파일
package com.demo.controller;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
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.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.demo.domain.AttachFileDTO;
import lombok.extern.log4j.Log4j;
import net.coobird.thumbnailator.Thumbnailator;
@Log4j
@Controller
@RequestMapping("/upload/*")
public class UploadController {
@GetMapping("/uploadForm")
public void uploadForm() {
}
// @PostMapping("/uploadFormAction")
// public void uploadFormPost(MultipartFile[] uploadFile) {
//
// for(MultipartFile multipartFile: uploadFile) {
// log.info("-------------------------------");
// log.info("파일이름 : " + multipartFile.getOriginalFilename());
// log.info("파일크기 : " + multipartFile.getSize());
// }
//
// }
@PostMapping("/uploadFormAction")
public void uploadFormPost(MultipartFile[] uploadFile) {
String uploadFolder = "C:\\Dev\\upload";
for(MultipartFile multipartFile: uploadFile) {
log.info("-------------------------------");
log.info("파일이름 : " + multipartFile.getOriginalFilename());
log.info("파일크기 : " + multipartFile.getSize());
File saveFile = new File(uploadFolder, multipartFile.getOriginalFilename());
try {
multipartFile.transferTo(saveFile); // 파일복사(업로드)
} catch (IllegalStateException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// Ajax작업
@GetMapping("/uploadAjax")
public void uploadAjax() {
}
@ResponseBody // 이 메서드만 리턴값을 json으로 변환
@PostMapping(value = "/uploadAjaxAction", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
public ResponseEntity<List<AttachFileDTO>> uploadAjaxAction(MultipartFile[] uploadFile){
ResponseEntity<List<AttachFileDTO>> entity = null;
List<AttachFileDTO> list = new ArrayList<AttachFileDTO>();
String uploadFolder = "C:\\Dev\\upload";
String uploadFolderPath = getFolder(); // "2022\06\29"
File uploadPath = new File(uploadFolder, uploadFolderPath); // C:\\Dev\\upload\\2022\\06\\29
// 위의 2가지 데이터가 존재하느냐
if(uploadPath.exists() == false) {
uploadPath.mkdirs();
}
log.info("경로 + 날짜 : " + uploadPath);
// 향상된 for문
for(MultipartFile multipartFile: uploadFile) {
// 업로드하고자 하는 파일정보를 저장목적
// 필드값 가져오기
AttachFileDTO attachFileDTO = new AttachFileDTO();
// 1)파일정보 : 클라이언트 파일이름
// 넣은 변수에 새로운변수를 만들어 이름을 넣고, 필드에 set시킨다
String uploadFileName = multipartFile.getOriginalFilename();
attachFileDTO.setFileName(uploadFileName);
// 중복되지 않는 문자열 생성
UUID uuid = UUID.randomUUID();
// 업로드시 중복되지 않는 파일이름을 생성
uploadFileName = uuid.toString() + "_" + uploadFileName;
try {
// 유일한 파일이름으로 객체생성
File saveFile = new File(uploadPath, uploadFileName);
multipartFile.transferTo(saveFile);
// 2)파일정보 : 중복되지 않은 고유의 문자열.
attachFileDTO.setUuid(uuid.toString());
// 3)파일정보 : 업로드 날짜폴더경로
attachFileDTO.setUploadPath(uploadFolderPath);
// 4)파일정보 : 이미지 또는 일반파일 여부
if(checkImageType(saveFile)) {
attachFileDTO.setImage(true);
// 섬네일 작업 : 원본이미지를 대상으로 사본이미지를 해상도의 손실을 줄이고, 크기를 작게 작업한다
FileOutputStream thumbnail = new FileOutputStream(new File(uploadPath, "s_" + uploadFileName));
Thumbnailator.createThumbnail(multipartFile.getInputStream(), thumbnail, 100, 100);
thumbnail.close();
}
list.add(attachFileDTO);
} catch(Exception e) {
e.printStackTrace();
}
}
entity = new ResponseEntity<List<AttachFileDTO>>(list, HttpStatus.OK);
log.info("entity : " + entity);
return entity; // list -> json으로 변환되어 리턴
}
// 날짜를 이용한 업로드 폴더생성 및 폴더이름 반환
private String getFolder() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
String str = sdf.format(date); // str = "2022-06-29"
log.info("파일 경로 호환 : " + str.replace("-", File.separator));
// File.separator : 운영체제에 따라서 파일경로 구분자를 반환. 예> 윈도우 c:\temp\... 리눅스 /home/etc/...
return str.replace("-", File.separator);
}
// 이미지 파일여부를 체크
private boolean checkImageType(File saveFile) {
boolean isImage = false;
try {
String contentType = Files.probeContentType(saveFile.toPath()); // text/html, text/plain, image/jpeg
isImage = contentType.startsWith("image");
} catch(Exception e) {
e.printStackTrace();
}
return isImage;
}
}
MVN Thumbnailator 검색
pom.xml에 추가
<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<!-- 썸네일 이미지 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
댓글남기기