본문 바로가기

웹 개발/Spring

[Web_Spring] 21

실습

- 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