일반 게시판에서 사진을 업로드 할 때 방법을 설명


먼저 JSP 파일


------------------------------------------------------------------------------------------------------------------------------------

출처: https://qdgbjsdnb.tistory.com/ [하위^^]
------------------------------------------------------------------------------------------------------------------------------------

출처: https://qdgbjsdnb.tistory.com/ [하위^^]

------------------------------------------------------------------------------------------------------------------------------------

<%@ 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>
<style>
    .outer {
        width:1000px;
        height:650px;
        background:black;
        color:white;
        margin-left:auto;
        margin-right:auto;
        margin-top:50px;
    }
    table {
        border:1px solid white;
    }
    .insertArea {
        width:500px;
        height:450px;
        margin-left:auto;
        margin-right:auto;
    }
    .btnArea {
        width:150px;
        margin-left:auto;
        margin-right:auto;
    }
    #titleImgArea {
        width:350px;
        height:200px;
        border:2px dashed darkgray;
        text-align:center;
        display:table-cell;
        vertical-align:middle;
    }
    #contentImgArea1, #contentImgArea2, #contentImgArea3 {
        width:150px;
        height:100px;
        border:2px dashed darkgray;
        text-align:center;
        display:table-cell;
        vertical-align:middle;
    }
</style>
</head>
<body>
    <%@ include file="../common/menubar.jsp" %>
    <% if(loginUser != null) { %>
    <div class="outer">
        <br>
        <h2 align="center">사진 게시판 작성</h2>
        <form action="<%=request.getContextPath() %>/insert.tn" method="post" encType="multipart/form-data"> <!-- 파일 전송 시 encType을 지정해야 한다. -->
            <div class="insertArea">
                <table align="center">
                    <tr>
                        <td>제목</td>
                        <td colspan="3"><input type="text" size="45" name="title"></td>
                    </tr>
                    <tr>
                        <td>대표 이미지</td>
                        <td colspan="3">
                            <div id="titleImgArea">
                                <img id="titleImg" width="350" height="200">
                            </div>
                        </td>
                    </tr>
                    <tr>
                        <td>내용사진</td>
                        <td>
                            <div id="contentImgArea1">
                                <img id="contentImg1" width="120" height="100">
                            </div>
                        </td>
                        <td>
                            <div id="contentImgArea2">
                                <img id="contentImg2" width="120" height="100">
                            </div>
                        </td>
                        <td>
                            <div id="contentImgArea3">
                                <img id="contentImg3" width="120" height="100">
                            </div>
                        </td>
                    </tr>
                    <tr>
                        <td width="100px">사진 메모</td>
                        <td colspan="3">
                            <textarea name="content" rows="5" cols="50" style="resize:none;"></textarea>
                        </td>
                    </tr>
                </table>
                <div id="fileArea">
                    <input type="file" id="thumbnailImg1" name="thumbnailImg1" onchange="loadImg(this, 1)">
                    <input type="file" id="thumbnailImg2" name="thumbnailImg2" onchange="loadImg(this, 2)">
                    <input type="file" id="thumbnailImg3" name="thumbnailImg3" onchange="loadImg(this, 3)">
                    <input type="file" id="thumbnailImg4" name="thumbnailImg4" onchange="loadImg(this, 4)">
                </div>
            </div>
            <div class="btnArea">
                <button>취소하기</button>
                <button type="submit">작성완료</button>
            </div>
        </form>
    </div>
   
    <script type="text/javascript">
        $(function() {
            $("#fileArea").hide(); // 버튼 숨기기
           
            $("#titleImgArea").click(function() {
                $("#thumbnailImg1").click();
            });
            $("#contentImgArea1").click(function() {
                $("#thumbnailImg2").click();
            });
            $("#contentImgArea2").click(function() {
                $("#thumbnailImg3").click();
            });
            $("#contentImgArea3").click(function() {
                $("#thumbnailImg4").click();
            });
        });
        /* function loadImg(value) { // 박스에 파일 업로드 하는 방법
            if (value.files && value.files[0]) {
                var reader = new FileReader();
               
                reader.onload = function(e) {
                    $("#titleImg").attr("src", e.target.result);
                };
               
                reader.readAsDataURL(value.files[0]);
            }
        } */
        function loadImg(value, num) { // value는 업로드한 파일
            if (value.files && value.files[0]) { // 파일을 업로드하면 배열 형태로 들어온다.
                var reader = new FileReader();
               
                reader.onload = function(e) { // reader가 실행되면 적용될 속성
                    switch (num) {
                    case 1 :
                        $("#titleImg").attr("src", e.target.result); // target.result는 업로드한 파일의 임시경로
                        break;
                    case 2 :
                        $("#contentImg1").attr("src", e.target.result);
                        break;
                    case 3 :
                        $("#contentImg2").attr("src", e.target.result);
                        break;
                    case 4 :
                        $("#contentImg3").attr("src", e.target.result);
                        break;
                    }
                };
               
                reader.readAsDataURL(value.files[0]); // reader호출, 파일의 url을 읽어 들임
            }
        }
    </script>
   
    <% } else { %>
    <%    
        request.setAttribute("msg", "잘못된 경로로 접근하셨습니다.");
        request.getRequestDispatcher("../common/errorPage.jsp").forward(request, response);
    %>
    <% } %>
</body>
</html>

------------------------------------------------------------------------------------------------------------------------------------


다른 폼은 여태껏 봐왔던 html 코드들인데


스크립트 부분을 설명하면


        $(function() {
            $("#fileArea").hide(); // 버튼 숨기기
           
            $("#titleImgArea").click(function() {
                $("#thumbnailImg1").click();
            });
            $("#contentImgArea1").click(function() {
                $("#thumbnailImg2").click();
            });
            $("#contentImgArea2").click(function() {
                $("#thumbnailImg3").click();
            });
            $("#contentImgArea3").click(function() {
                $("#thumbnailImg4").click();
            });
        });


이 부분은 이미지 박스를 눌렀을 때 버튼 기능을 실행하게 하고


버튼은 숨겨 안보이게 표시하는 스크립트




        /* function loadImg(value) { // 박스에 파일 업로드 하는 방법
            if (value.files && value.files[0]) {
                var reader = new FileReader();
               
                reader.onload = function(e) {
                    $("#titleImg").attr("src", e.target.result);
                };
               
                reader.readAsDataURL(value.files[0]);
            }
        } */


type="file"에 함수를 만들어 value를 인자로 받았을 때


value는 받은 파일을 의미하게 된다.


value는 여러개가 들어올 수 있으므로 배열 형태로 들어오게 되고


files 라는 메소드는 파일이 있는지 없는지를 반환한다.




FileReader 객체를 생성하고 불러올 때 작동할 함수(onload)는 클릭한 박스의 속성의 이미지를 등록하는 것이다.


function(e) 의 e는 등록한 파일을 의미하고 e.target.result는 서버에 업로드 하기 전에 임시로 지정된 파일의 경로가 된다.


reader.readAsDataURL(value.files[0])은 파일의 경로를 한번 불러오는 것이고 호출했기 때문에 onload가 작동된다.






        function loadImg(value, num) { // value는 업로드한 파일
            if (value.files && value.files[0]) { // 파일을 업로드하면 배열 형태로 들어온다.
                var reader = new FileReader();
               
                reader.onload = function(e) { // reader가 실행되면 적용될 속성
                    switch (num) {
                    case 1 :
                        $("#titleImg").attr("src", e.target.result); // target.result는 업로드한 파일의 임시경로
                        break;
                    case 2 :
                        $("#contentImg1").attr("src", e.target.result);
                        break;
                    case 3 :
                        $("#contentImg2").attr("src", e.target.result);
                        break;
                    case 4 :
                        $("#contentImg3").attr("src", e.target.result);
                        break;
                    }
                };
               
                reader.readAsDataURL(value.files[0]); // reader호출, 파일의 url을 읽어 들임
            }
        }



2번째 스크립트의 확장으로 이미지 선택 박스의 종류 별 기능을 활성화 한다.








submit으로 설정한 버튼을 통해서


<form action="<%=request.getContextPath() %>/insert.tn" method="post" encType="multipart/form-data"> 부분의


<%=request.getContextPath() %>/insert.tn 주소로 맵핑된 부분으로 이동된다.


이동된 부분은 Servlet 파일로 서버에 업로드 된 파일을 처리한다.


단, 파일을 보낼 때는 form 속성에 무조건 encType="multipart/form-data" 를 명시해야 한다.








다음으로는 Servlet 파일

------------------------------------------------------------------------------------------------------------------------------------

package com.kh.jsp.board.controller;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;

import com.kh.jsp.board.model.service.BoardService;
import com.kh.jsp.board.model.vo.Attachment;
import com.kh.jsp.board.model.vo.Board;
import com.kh.jsp.common.MyFileRenamePolicy;
import com.kh.jsp.member.model.vo.Member;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;

@WebServlet("/insert.tn")
public class InsertThumbnailServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
      
    public InsertThumbnailServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String title = request.getParameter("title");
        System.out.println(title);
        // encType="multipart/form-data"로 데이터를 넘기면 null이 출력된다.
        // 폼전송을 multipart/form-date로 전송하는 경우에는
        // 기존처럼 request.getParameter로 값을 받을 수 없다.
       
        // cos.jar가 파일도 받고 다른 값들도 받아주는 역할을 한다.
        // com.oreilly.servlet의 약자이다.
        // http://servlets.com/cos/ 맨 아래에서 다운로드해서 lib에 추가한다.
       
        if(ServletFileUpload.isMultipartContent(request)) {
            // 전송 파일 용량 제한 : 10MB로 제한되어 있다. 그 이상은 유료
            int maxSize = 1024 * 1024; // (1mb)로 설정
           
            String root = request.getSession().getServletContext().getRealPath("/");
            System.out.println(root); // 톰캣 설정 첫번째 항목 체크를 안하면 경로가 톰캣으로 잡혀버린다.
            // thumbnale_uploadFiles 라는 폴더가 해당 경로 아래에 생기게 되므로 다음과 같이 파일 경로를 설정하자
           
            String filePath = root + "thumbnale_uploadFiles/";
           
            // MultipartRequest multiRequest = new MultipartRequest(request, filePath, maxSize, "UTF-8", new DefaultFileRenamePolicy());            // 사용자가 올린 파일명을 그대로 저장하지 않는 것이 일반적이다.
            // 1. 같은 파일명이 있는 경우 이전 파일을 덮어 쓸 수 있다.
            // 2. 한글로된 파일명, 특수기호, 띄어쓰기는 서버에 따라 문제가 생길 여지가 있다.
            // DefaultFileRenamePolicy는 cos.jar에서 제공하는 클래스
            // 같은 파일명이 존재하는지를 체크하고 있을 경우에는 뒤에 숫자를 붙여준다.
            // ex) aaa.zip, aaa1.zip, aaa2.zip
            MultipartRequest multiRequest = new MultipartRequest(request, filePath, maxSize, "UTF-8", new MyFileRenamePolicy());
           
            // 다중 파일을 묶어서 업로드 하기 위해 컬렉션 사용
            // 저장한 파일의 이름을 저장할 arrayList 생성
            ArrayList<String> saveFiles = new ArrayList<String>();
           
            // 원본 파일의 이름을 저장 할 ArrayList 생성
            ArrayList<String> originFiles = new ArrayList<String>();
           
            // 각 파일의 정보를 구해온 뒤 DB에 저장할 목적의 데이터를 꺼내온다.
            Enumeration<String> files = multiRequest.getFileNames();
           
            while (files.hasMoreElements()) {
                String name = files.nextElement();
               
                System.out.println(name);
               
                saveFiles.add(multiRequest.getFilesystemName(name));
                originFiles.add(multiRequest.getOriginalFileName(name));
               
                System.out.println("FileSystem name : " + multiRequest.getFilesystemName(name));
                System.out.println("originFile name : " + multiRequest.getOriginalFileName(name));
            }
           
            String multiTitle = multiRequest.getParameter("title");
            String multiContent = multiRequest.getParameter("content");
            System.out.println(multiTitle);
            System.out.println(multiContent);
           
            //Board객체 생성
            Board b = new Board();
            b.setbTitle(multiTitle);
            b.setbContent(multiContent);
            b.setbWriter(String.valueOf(((Member)(request.getSession().getAttribute("loginUser"))).getUno()));
           
            // Attachment 객체 생성하여 arrayList 객체 생성
            ArrayList<Attachment> fileList = new ArrayList<Attachment>();
           
            for(int i = originFiles.size() - 1; i >= 0; i--) {
                Attachment at = new Attachment();
                at.setFilePath(filePath);
                at.setOriginName(originFiles.get(i));
                at.setChangeName(saveFiles.get(i));
               
                fileList.add(at);
               
            }
           
            int result = new BoardService().insertThumbnail(b, fileList);
           
            if (result > 0) {
                response.sendRedirect(request.getContextPath() + "/selectList.tn");
            } else {
                // 실패 시 저장된 사진 삭제
                for (int i = 0; i < saveFiles.size(); i++) {
                    // 파일 시스템에 저장된 이름으로 파일 객체 생성
                    File failedFile = new File(filePath + saveFiles.get(i));
                   
                    // true, false를 리턴함
                    failedFile.delete();
                }
               
                request.setAttribute("msg", "사진게시판 등록 실패!");
                request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
            }
           
           
        }
       
       
    }
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

------------------------------------------------------------------------------------------------------------------------------------


        // cos.jar가 파일도 받고 다른 값들도 받아주는 역할을 한다.
        // com.oreilly.servlet의 약자이다.
        // http://servlets.com/cos/ 맨 아래에서 다운로드해서 lib에 추가한다.


부분은 사진으로 추가 설명


http://servlets.com/cos/ 링크로 이동




다운받은 압축파일을 풀어 lib폴더에 복사하면 된다.


대부분의 설명은 주석에 되어 있으므로 안 되있는 부분만 설명




Enumeration<String> files = multiRequest.getFileNames(); 경우는 파일을 리스트 형식으로 알아서 불러오는 객체이다.







서블릿 부분에서 데이터를 정리해서 DB 쪽으로 연결하는 코드는 아래 한 줄 부분이다.

int result = new BoardService().insertThumbnail(b, fileList);




다음은 Service 부분

------------------------------------------------------------------------------------------------------------------------------------

public int insertThumbnail(Board b, ArrayList<Attachment> fileList) {
        Connection con = getConnection();
       
        int result = 0;
       
        int result1 = new BoardDao().insertThumbnailContent(con, b);
       
        if (result1 > 0) {
            int bid = new BoardDao().selectCurrval(con);
           
            for(int i = 0; i < fileList.size(); i++) {
                fileList.get(i).setBid(bid);
            }
        }
       
        int result2 = new BoardDao().insertAttachment(con, fileList);
       
        if (result1 > 0 && result2 > 0) {
            commit(con);
            result = 1;
        } else {
            rollback(con);
        }
       
        close(con);
       
       
        return result;
    }

------------------------------------------------------------------------------------------------------------------------------------

이 부분에서는 DB에 3번의 접근이 일어나게 된다.


첫번째는 게시글 테이블에 등록


두번째는 게시글 번호 불러오기(시퀀스를 통해서 등록한 게시글 번호를 불러온다.)


세번째는 첨부파일 테이블에 게시글 번호(외래키)와 함께 파일을 등록한다.







Dao 부분은 전과 같이 DB에 Prestatement나 statement를 사용하여 쿼리문을 사용한다.

여태껏 해온 부분과 비슷하므로 생략


+ Recent posts