20240223 스프링(파일 체크, 파일 업로드 , 갤러리 만들기)

2024. 2. 23. 17:492023.11.21-2024.05.31

	public String fileUpload(MultipartFile upFile) {
		//경로 저장
		String root = req().getSession().getServletContext().getRealPath("/");
		String upfilePath = root + "resources\\upfile\\";
		//UUID
		UUID uuid = UUID.randomUUID();
		//uuid를 포함한 파일명
		
		String newFileName = uuid.toString()+ upFile.getOriginalFilename();
		
		//실제 업로드
		File file = new File(upfilePath, newFileName);
		try {
			upFile.transferTo(file);
		} catch (IllegalStateException e) {
			
			e.printStackTrace();
		} catch (IOException e) {
			
			e.printStackTrace();
		}
		
		return newFileName;
	}​
 //파일 업로드 -> util
	    String newFileName = util.fileUpload(upFile);
	    
	    dto.setGfile(upFile.getOriginalFilename());
		
		
		int result = galleryService.galleryInsert(dto);
		return "redirect:/gallery";

파일jsp >  onsubmit="fileCheck()" 추가

         	<form action="./file" method="post" enctype="multipart/form-data" onsubmit="fileCheck()">

 

스크립트 만들기

   <script type="text/javascript">
   function fileCheck(){
		var fileVal = $("#file1").val();// 파일이름 가져오기
		if( fileVal == ""){
			alert('파일을 선택하세요.');
			return false;
		} else {
			var ext = fileVal.split('.').pop().toLowerCase();//확장자분리
			//아래 확장자가 있는지 체크
			if($.inArray(ext, ['jsp', 'jpeg','gif', 'png']) == -1){
				alert('jpg,gif,jpeh,png 파일만 업로드 할 수 있습니다.');
				return fase;
			}
			
		}
		//Swal.fire("댓글의 길이가 짧습니다", "댓글은 10글자 이상이어야 합니다.", "waring");
		}
   </script>

 

 

 

 

메뉴> 갤러리 추가

<div class="collapse navbar-collapse" id="navbarResponsive">
			<ul class="navbar-nav text-uppercase ms-auto py-4 py-lg-0">
				<li class="nav-item"><a class="nav-link" href="./board">게시판</a></li>
				<li class="nav-item"><a class="nav-link" href="./gallery">갤러리</a></li>
				<li class="nav-item"><a class="nav-link" href="./file">파일</a></li>
				<li class="nav-item"><a class="nav-link" href="./mail">메일</a></li>
				<li class="nav-item"><a class="nav-link" href="./notice">공지사항</a></li>
				<c:choose>
					<c:when test="${sessionScope.mid ne null }">
						<li class="nav-item"><a class="nav-link"
							href="./myInfo@${sessionScope.mid }">${sessionScope.mname } 님</a></li>
						<li class="nav-item"><a class="nav-link" href="./logout">로그아웃</a></li>
					</c:when>
					<c:otherwise>
						<li class="nav-item"><a class="nav-link" href="./login">로그인</a></li>
					</c:otherwise>
				</c:choose>

 

 

갤러리컨트롤러 만들기

package org.mask.controller;

import org.mask.dto.GalleryDTO;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class GalleryController {

	@GetMapping("/gallery")
	public String gallery() {
		return "gallery";
	}
	
	@PostMapping("/galleryInsert")
	public String galleryInset(GalleryDTO dto) {
		return "redirect:/gallery";
	}
}

 

 

갤러리dto 만들기

package org.mask.dto;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class GalleryDTO {

	private int gno, glike, gdel;
	private String gtitle, gcontent, gfile, gthumbnail, gdate, mname, mid;
}

 

데이터베이스 만들기

 

 

 

갤러리 DAO

package org.mask.dao;

import org.apache.ibatis.session.SqlSession;
import org.mask.dto.GalleryDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class GalleryDAO {

	@Autowired
	private SqlSession sqlSession;
	
	public int galleryInsert(GalleryDTO dto) {
		return sqlSession.insert("gallery.galleryInsert", dto);
	}
	
}

 

갤러리 서비스

@Service
public class GalleryService {
	@Autowired
	private GalleryDAO galleryDAO;
	
	@Autowired
	Util util;
	
	public int galleryInsert(GalleryDTO dto) {
		//세션 추가
		if(util.getSession().getAttribute("mid") != null) {
			dto.setMid((String) util.getSession().getAttribute("mid"));
			return galleryDAO.galleryInsert(dto);			
		} else {
			return 0;
		}
	}

 

 

갤러리 컨트롤러

package org.mask.controller;

import org.mask.dto.GalleryDTO;
import org.mask.service.GalleryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class GalleryController {
	
	@Autowired
	private GalleryService galleryService;

	@GetMapping("/gallery")
	public String gallery() {
		return "gallery";
	}
	
	@GetMapping("/galleryInsert")
	public String galleryInsert() {
		return "galleryInsert";
	}
	
	@PostMapping("/galleryInsert")
	public String galleryInset(GalleryDTO dto) {
		return "redirect:/gallery";
	}
}

 

 

매퍼

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="gallery">
	<insert id="galleryInsert" parameterType="galleryDTO">
		INSERT INTO gallery (gtitle, gcontent, gfile, mno) VALUES (#{gtitle},
		#{gcontent}, #{gfile}, (SELECT mno FROM member WHERE mid=#{mid}))
	</insert>
</mapper>

 

갤러리JSP,

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
        <meta name="description" content="" />
        <meta name="author" content="" />
        <title>Trinity Company - 갤러리</title>
        <!-- Favicon-->
        <link rel="icon" type="image/x-icon" href="assets/favicon.ico" />
        <link rel="shortcut icon" type="image/x-icon" href="assets/favicon.ico" />
        <link rel="apple-touch-icon" sizes="57x57" href="assets/apple-icon-57x57.png">
		<link rel="apple-touch-icon" sizes="60x60" href="assets/apple-icon-60x60.png">
		<link rel="apple-touch-icon" sizes="72x72" href="assets/apple-icon-72x72.png">
		<link rel="apple-touch-icon" sizes="76x76" href="assets/apple-icon-76x76.png">
		<link rel="apple-touch-icon" sizes="114x114" href="assets/apple-icon-114x114.png">
		<link rel="apple-touch-icon" sizes="120x120" href="assets/apple-icon-120x120.png">
		<link rel="apple-touch-icon" sizes="144x144" href="assets/apple-icon-144x144.png">
		<link rel="apple-touch-icon" sizes="152x152" href="assets/apple-icon-152x152.png">
		<link rel="apple-touch-icon" sizes="180x180" href="assets/apple-icon-180x180.png">
		<link rel="icon" type="image/png" sizes="192x192"  href="assets/android-icon-192x192.png">
		<link rel="icon" type="image/png" sizes="32x32" href="assets/favicon-32x32.png">
		<link rel="icon" type="image/png" sizes="96x96" href="assets/favicon-96x96.png">
		<link rel="icon" type="image/png" sizes="16x16" href="assets/favicon-16x16.png">
		<link rel="manifest" href="assets/manifest.json">
		<meta name="msapplication-TileColor" content="#ffffff">
		<meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
		<meta name="theme-color" content="#ffffff">
        <!-- Font Awesome icons (free version)-->
        <script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
        <!-- Google fonts-->
        <link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet" type="text/css" />
        <link href="https://fonts.googleapis.com/css?family=Roboto+Slab:400,100,300,700" rel="stylesheet" type="text/css" />
        <!-- Core theme CSS (includes Bootstrap)-->
        <link href="css/styles.css" rel="stylesheet" />
        <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
        <script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
        <script type="text/javascript">
        const Toast = Swal.mixin({
        	  toast: true,
        	  position: 'center-center',
        	  showConfirmButton: false,
        	  timer: 3000,
        	  timerProgressBar: true,
        	  didOpen: (toast) => {
        	    toast.onmouseenter = Swal.stopTimer;
        	    toast.onmouseleave = Swal.resumeTimer;
        	  }
        	});
        
	
	}        
        </script>
    </head>
    <body id="page-top">
        <!-- Navigation-->
        <%@ include file="menu.jsp" %>
        
        <!-- gallery -->
        <section class="page-section" id="gallery">
            <div class="container">
			<div class="text-center">				
			
			
				<table>
					<thead>
					<tr>
						<th>번호</th>
						<th>제목</th>
						<th>이미지</th>
						<th>날짜</th>
						<th>좋아요</th>
					</tr>
					</thead>
					<tbody>
					<c:forEach items="${list }" var="row">
						<tr>
							<td>${row.gno }</td>
							<td>${row.gtitle }</td>
							<td>
								<img alt="" src="./upfile/s_${row.gfile }">
							</td>
							<td>${row.gdate }</td>
							<td>${row.glike }</td>
						</tr>
					</c:forEach>		
					</tbody>
				</table>
			
			
			
  					<button class="btn btn-outline-secondary" type="submit" onclick="location.href='./galleryInsert'">글쓰기</button>
            </div>
            </div>
        </section>
        
        <!-- Bootstrap core JS-->
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
        <!-- Core theme JS-->
        <script src="js/scripts.js"></script>
        <!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *-->
        <!-- * *                               SB Forms JS                               * *-->
        <!-- * * Activate your form at https://startbootstrap.com/solution/contact-forms * *-->
        <!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *-->
        <script src="https://cdn.startbootstrap.com/sb-forms-latest.js"></script>
    </body>
</html>

 

갤러리인서트 JSP

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
    <meta name="description" content="" />
    <meta name="author" content="" />
    <title>Trinity Company - 갤러리 게시판 글쓰기</title>
    <!-- Favicon-->
    <link rel="icon" type="image/x-icon" href="assets/favicon.ico" />
    <link rel="shortcut icon" type="image/x-icon" href="assets/favicon.ico" />
    <link rel="apple-touch-icon" sizes="57x57" href="assets/apple-icon-57x57.png">
    <link rel="apple-touch-icon" sizes="60x60" href="assets/apple-icon-60x60.png">
    <link rel="apple-touch-icon" sizes="72x72" href="assets/apple-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="76x76" href="assets/apple-icon-76x76.png">
    <link rel="apple-touch-icon" sizes="114x114" href="assets/apple-icon-114x114.png">
    <link rel="apple-touch-icon" sizes="120x120" href="assets/apple-icon-120x120.png">
    <link rel="apple-touch-icon" sizes="144x144" href="assets/apple-icon-144x144.png">
    <link rel="apple-touch-icon" sizes="152x152" href="assets/apple-icon-152x152.png">
    <link rel="apple-touch-icon" sizes="180x180" href="assets/apple-icon-180x180.png">
    <link rel="icon" type="image/png" sizes="192x192" href="assets/android-icon-192x192.png">
    <link rel="icon" type="image/png" sizes="32x32" href="assets/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="96x96" href="assets/favicon-96x96.png">
    <link rel="icon" type="image/png" sizes="16x16" href="assets/favicon-16x16.png">
    <link rel="manifest" href="assets/manifest.json">
    <meta name="msapplication-TileColor" content="#ffffff">
    <meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
    <meta name="theme-color" content="#ffffff">
    <!-- Font Awesome icons (free version)-->
    <script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
    <!-- Google fonts-->
    <link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet" type="text/css" />
    <link href="https://fonts.googleapis.com/css?family=Roboto+Slab:400,100,300,700" rel="stylesheet" type="text/css" />
    <!-- Core theme CSS (includes Bootstrap)-->
    <link href="css/styles.css" rel="stylesheet" />
    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
    <script type="text/javascript">
        const Toast = Swal.mixin({
            toast: true,
            position: 'center-center',
            showConfirmButton: false,
            timer: 3000,
            timerProgressBar: true,
            didOpen: (toast) => {
                toast.onmouseenter = Swal.stopTimer;
                toast.onmouseleave = Swal.resumeTimer;
            }
        });

        function fileCheck() {
            var fileVal = $("#file1").val(); // 파일이름 가져오기
            if (fileVal == "") {
                alert('파일을 선택하세요.');
                return false;
            } else {
                var ext = fileVal.split('.').pop().toLowerCase(); //확장자분리
                //아래 확장자가 있는지 체크
                if ($.inArray(ext, ['jpg', 'jpeg', 'gif', 'png']) == -1) {
                    alert('jpg,gif,jpeg,png 파일만 업로드 할 수 있습니다.');
                    return false;
                }
            }
            //Swal.fire("댓글의 길이가 짧습니다","댓글은 10글자 이상이어야 합니다.", "warning");
        }
    </script>
</head>

<body id="page-top">
    <!-- Navigation-->
    <%@ include file="menu.jsp" %>

    <!-- 갤러리 글쓰기 -->
    <section class="page-section" id="gallery">
        <div class="container">
            <div class="text-center">
                <h1 class="mt-5">갤러리 글쓰기</h1>
                <form action="./galleryInsert" method="post" enctype="multipart/form-data" onsubmit="return fileCheck()">
                    <div class="input-group mb-3">
                        <span class="input-group-text" id="basic-addon3">제목</span>
                        <input type="text" name="gtitle" class="form-control" id="basic-url" aria-describedby="basic-addon3">
                    </div>
                    <div class="input-group mb-3" style="height: 300px;">
                        <span class="input-group-text">내용</span>
                        <textarea class="form-control" aria-label="With textarea" name="gcontent"></textarea>
                    </div>
                    <div class="input-group mb-3">
                        <input type="file" accept="image/*" id="file1" name="file1" class="form-control">
                    </div>
                    <div class="input-group mb-3">
                        <button class="btn btn-outline-secondary" type="submit">업로드</button>
                    </div>
                </form>

            </div>
        </div>
    </section>

    <!-- Bootstrap core JS-->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
    <!-- Core theme JS-->
    <script src="js/scripts.js"></script>
    <!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *-->
    <!-- * *                               SB Forms JS                               * *-->
    <!-- * * Activate your form at https://startbootstrap.com/solution/contact-forms * *-->
    <!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *-->
    <script src="https://cdn.startbootstrap.com/sb-forms-latest.js"></script>
</body>

</html>

 

 

 

갤러리 jsp 꾸며주기.

화면에 띄우게 해보기

 

 

 

 

갤러리컨트롤러

	@PostMapping("/galleryInsert")
	public String galleryInset(GalleryDTO dto) {
		System.out.println(dto.getGtitle());
		System.out.println(dto.getGcontent());
		
		int result = galleryService.galleryInsert(dto);
		return "redirect:/gallery";
	}

 

 

디비에 실제로 저장되기 수정된 부분이 많으니까 자세히 살펴보기

 

 

 

갤러리컨트롤러>유틸 fileUpload 추가

	   //파일 업로드 -> util
	    String newFileName = util.fileUpload(upFile);
	    
	    dto.setGfile(upFile.getOriginalFilename());
		
		
		int result = galleryService.galleryInsert(dto);
		return "redirect:/gallery";

 

 

유틸> fileUpload 추가

	public String fileUpload(MultipartFile upFile) {
		//경로 저장
		String root = req().getSession().getServletContext().getRealPath("/");
		String upfilePath = root + "resources\\upfile\\";
		//UUID
		UUID uuid = UUID.randomUUID();
		//uuid를 포함한 파일명
		
		String newFileName = uuid.toString()+ upFile.getOriginalFilename();
		
		//실제 업로드
		File file = new File(upfilePath, newFileName);
		if(file.exists() == false) {
			file.mkdirs();//경로가 없다면 다 만들어주기.
			
		}
		try {
			FileOutputStream thumbnail = new FileOutputStream(new File(upfilePath, "s_"+newFileName));
			Thumbnailator.createThumbnail(upFile.getInputStream(), thumbnail,100, 100 );
			thumbnail.close();
		} catch (IllegalStateException e) {
			
			e.printStackTrace();
		} catch (IOException e) {
			
			e.printStackTrace();
		}
		
		return newFileName;
	}

 

여기까지 잘 됐으면, 데이터베이스에 저장도 되고, 실제 경로에도 저장이 되면 된다.

 

 

화면에 띄우기

갤러리 컨트롤러 > @GetMapping("/gallery") 수정

	@GetMapping("/gallery")
	public String gallery(Model model) {
		List<GalleryDTO> list = galleryService.galleryList();
		model.addAttribute("list", list);
		return "gallery";
	}

 

갤러리 서비스>

	public List<GalleryDTO> galleryList() {
		
		return galleryDAO.galleryList();
	}

 

갤러리 다오>

public List<GalleryDTO> galleryList() {
		
		return sqlSession.selectList("gallery.galleryList");
	}

 

 

매퍼

 

갤러리jsp

 <!-- 갤러리 글쓰기 -->
   <section class="page-section" id="gallery">
      <div class="d-flex justify-content-center">
         <div class="text-center">
         
         <table>
         	<thead>
         	<tr>
         		<th>번호</th>
         		<th>제목</th>
         		<th>이미지</th>
         		<th>날짜</th>
         		<th>좋아요</th>
         	</tr>
         	</thead>
         	<tbody>
         	
         	<c:forEach items="${lis }" var="row>">
         		<tr>
         			<td>${row.gno }</td>
         			<td>${row.gtitle }</td>
         			<td>${row.gno }</td>
         			<td>
         				<img alt="" src="./upfile/s_${row.gfile }">
         			</td>
         			<td>${row.gdate }</td>
         			<td>${row.glike }</td>
         			<tr>
         	</c:forEach>
         	</tbody>		
         </table>

 

아래처럼 나오면 된다.