실습
- board 이어서
1. src/main/resource/application.properties
#server port
server.port=10003
#JDBC spy datasource
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
spring.datasource.hikari.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.hikari.jdbc-url=jdbc:log4jdbc:oracle:thin:@localhost:1521:XE
spring.datasource.hikari.username=hr
spring.datasource.hikari.password=hr
#log level
logging.level.root=info
#multipart
spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=40MB
spring.servlet.multipart.max-request-size=100MB
spring.servlet.multipart.file-size-threshold=100MB
2. src/main/java/com.example.board/domain/dao/AttachDAO.java
package com.example.board.domain.dao;
import com.example.board.domain.vo.AttachFileVO;
import com.example.board.mapper.AttachMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
@Repository
@RequiredArgsConstructor
public class AttachDAO {
private final AttachMapper attachMapper;
public void save(AttachFileVO attachFileVO){
attachMapper.insert(attachFileVO);
}
}
3. src/main/java/com.example.board/domain/vo/AttachFileVO.java
package com.example.board.domain.vo;
import lombok.Data;
import org.springframework.stereotype.Component;
@Component
@Data
public class AttachFileVO {
private String fileName;
private String originalFileName;
private String uploadDirectory;
private boolean image;
// 다대일
private BoardVO boardVO;
}
4. src/main/java/com.example.board/domain/vo/BoardVO.java
package com.example.board.domain.vo;
import lombok.Data;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Data
public class BoardVO {
private Long boardNumber;
private String boardTitle;
private String boardContent;
private String boardWriter;
private String boardRegisterDate;
private String boardUpdateDate;
// 일대다 관계
private List<AttachFileVO> fileList;
}
5. src/main/java/com.example.board/mapper/AttachMapper.java
package com.example.board.mapper;
import com.example.board.domain.vo.AttachFileVO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface AttachMapper {
public void insert(AttachFileVO attachFileVO);
}
6. src/main/resource/mapper/AttachMapper.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.board.mapper.AttachMapper">
<insert id="insert">
INSERT INTO TBL_ATTACH
(FILE_NAME, ORIGINAL_FILE_NAME, UPLOAD_DIRECTORY, IMAGE, BOARD_NUMBER)
VALUES(#{fileName}, #{originalFileName}, #{uploadDirectory}, #{image}, #{boardVO.boardNumber})
</insert>
</mapper>
7. src/main/resource/templates/board/register.html
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Board</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<link rel="stylesheet" href="/css/main.css" />
<style>
.result {
width: 100%;
}
.result ul {
display: flex;
justify-content: center;
overflow-x: scroll;
}
.result ul li {
list-style: none;
padding: 15px;
}
</style>
</head>
<body class="is-preload">
<!-- Main -->
<div id="main">
<div class="wrapper">
<div class="inner">
<!-- Elements -->
<header class="major">
<h1>Board</h1>
<p>게시글 등록</p>
</header>
<!-- Table -->
<h3><a href="/board/list" class="button small">목록 보기</a></h3>
<div class="content">
<div class="form">
<form method="post" action="/board/register" id="registForm">
<div class="fields">
<div class="field">
<h4>제목</h4>
<input name="boardTitle" placeholder="Title" type="text" />
</div>
<div class="field">
<h4>내용</h4>
<textarea name="boardContent" rows="6" placeholder="Content" style="resize:none"></textarea>
</div>
<div class="field">
<h4>작성자</h4>
<input name="boardWriter" placeholder="Writer" type="text" />
</div>
<div class="field">
<h4>첨부파일</h4>
<input type="file" name="files" multiple>
</div>
<div class="field">
<div class="result">
<ul></ul>
</div>
</div>
</div>
<ul class="actions special">
<li><input type="submit" class="button" value="등록" /></li>
</ul>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
<!-- Scripts -->
<script src="/js/jquery.min.js"></script>
<script src="/js/jquery.dropotron.min.js"></script>
<script src="/js/browser.min.js"></script>
<script src="/js/breakpoints.min.js"></script>
<script src="/js/util.js"></script>
<script src="/js/main.js"></script>
<script>
let regex = new RegExp("(.*?)\.(exe|sh|zip|alz)$");
let maxSize = 5242880; // 5MB
const result = $("div.result ul");
function checkExtension(fileName, fileSize){
if(regex.test(fileName)){
alert("(" + fileName + ")업로드 할 수 없는 파일의 형식입니다.")
return false;
}
if(fileSize >= maxSize){
alert("(" + fileName + ")파일 사이즈 초과")
return false;
}
return true;
}
$("input[type='submit']").on("click", function(e){
e.preventDefault();
let $form = $("form#registForm");
let str = "";
$.each($(".result ul li"), function(i, li){
str += "<input type='hidden' name='fileList[" + i + "].fileName' value='" + $(li).data('name') +"'>"
str += "<input type='hidden' name='fileList[" + i + "].originalFileName' value='" + $(li).data('original') +"'>"
str += "<input type='hidden' name='fileList[" + i + "].uploadDirectory' value='" + $(li).data('directory') +"'>"
str += "<input type='hidden' name='fileList[" + i + "].image' value='" + $(li).data('image') +"'>"
});
$form.append(str).submit();
})
//업로드 전
let arFile = Array.from($("input[type='file']")[0].files);
$("input[type='file']").on("change", function(e){
let formData = new FormData();
let input = $("input[name='files']"); // 업로드 후
let files = input[0].files;
console.log(files);
for(let i=0; i<files.length; i++){
if(checkExtension(files[i].name, files[i].size)){
formData.append("files", files[i]);
}
}
const dataTransfer = new DataTransfer();
//사용자가 업로드한 파일들의 정보를 전역변수인 arFile에 담아놓기
Array.from($(input[0].files)).forEach(file => arFile.push(file));
//전역변수의 전체 파일들을 FileList타입으로 변경
arFile.forEach(file => dataTransfer.items.add(file));
//input태그에 그 동안 업로드했던 모든 파일의 정보로 덮어 씌우기
input[0].files = dataTransfer.files;
$.ajax({
url: "/upload/uploadAjax",
type: "post",
data: formData,
processData: false,
contentType: false,
success: function(fileList){
showUploadFile(fileList);
}
});
});
function showUploadFile(fileList){
let str = "";
$.each(fileList, function(i, file){
str += "<li data-name='" + file.fileName + "' data-original='" + file.originalFileName + "' data-directory='" + file.uploadDirectory + "' data-image='" + file.image + "'>";
str += "<span data-name='" + file.originalFileName + "' data-path='" + file.uploadDirectory + "/t_" + file.fileName + "' style='cursor: pointer'>x</span>";
str += "<a href='/upload/download?path=" + file.uploadDirectory + "/" + file.fileName + "'>"
str += file.image ? "<img src='/upload/display?path=" + file.uploadDirectory + "/t_" + file.fileName + "'>"
: "<img src='/images/attach.png' width='100'>";
str += "</a><p>" + file.originalFileName + "</p>";
str += "</li>";
});
result.append(str);
}
$(".result").on("click", "span", function(e){
let path = $(this).data("path");
let li = $(this).closest("li");
//x버튼을 눌렀을 때 삭제될 파일의 원본 이름
let fileName = $(this).data("name");
console.log(fileName);
$.ajax({
url: "/upload/delete",
type: "delete",
data: {path: path},
success: function(){
const dataTransfer = new DataTransfer();
li.remove();
//원래 있었던 파일들에서
for(let i=0; i<arFile.length; i++){
//삭제한 파일의 이름과 동일한 파일을 검사
if(arFile[i].name == fileName){
//삭제된 파일은 기존 파일들에서 삭제시켜야 한다.
arFile.splice(i, 1);
}
}
//삭제된 파일을 제외한 나머지 파일들을
arFile.forEach(file => dataTransfer.items.add(file));
//input태그에 다시 담아준다.
$("input[type='file']")[0].files = dataTransfer.files;
}
});
});
</script>
</html>
'웹 개발 > Spring' 카테고리의 다른 글
[Web_Spring] 22 (0) | 2022.07.04 |
---|---|
[Web_Spring] 20 (0) | 2022.07.02 |
[Web_Spring] 23 (0) | 2022.07.01 |
[Web_Spring] 19 (0) | 2022.07.01 |
[Web_Spring] 18 (0) | 2022.06.30 |