고래씌
[JSP] 5-4. 사진게시판(썸네일) 본문
1. 사진게시판에 썸네일 리스트 만들기
▶ views-board 폴더에 thumbnailListView.jsp 파일 생성
■ thumbnailListView.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.ArrayList, com.kh.board.model.vo.Board"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
.list-area{
width:760px;
margin: 0 auto;
}
.outer{
width:1000px;
height: auto;
}
</style>
</head>
<body>
<%@ include file="../common/menubar.jsp" %>
<div class="outer">
<br>
<h2 align="center">사진게시판</h2>
<br>
<!-- 로그인한 사용자만 글작성이 보이도록 -->
<% if(loginUser != null) { %>
<div align="right" style="width:850px">
<a href="<%= contextPath %>/insert.th" class="btn btn-secondary">글작성</a>
<br>
<br>
</div>
<% } %>
<div class='list-area'>
<%
ArrayList<Board> list = (ArrayList<Board>) request.getAttribute("list");
%>
<%if(list.isEmpty()) { %>
<%-- 등록된 게시글이 없다면 --%>
등록된 게시글이 없습니다.
<% } else { %>
<% for(Board b : list) { %>
<div class="thumbnail" align="center">
<%-- 썸네일 게시판 상세보기로 들어가면 BoardNo가 필요하기 때문에 hidden으로 게시판 번호를 넘겨줌 --%>
<input type="hidden" value="<%= b.getBoardNo() %>">
<img src="<%= contextPath %>/<%= b.getAttachment().getFilePath()
+b.getAttachment().getChangeName() %>"
width="200px" height="150px">
<%-- b.getAttachment().getFilePath()+b.getAttachment().getChangeName()
=> 썸네일들의 경로를 가져옴 --%>
<p>
No.<%= b.getBoardNo() %> <%= b.getBoardTitle() %> <br>
조회수 : <%=b.getCount() %>
</p>
</div>
<% } %>
<% } %>
</div>
</div>
</body>
</html>
▶ menubar.jsp 에 경로 추가
▶ common.css 파일에 style 속성 추가
▶ resources 폴더 아래에 thumbnail_upfiles 폴더 생성
- jpg 파일 저장되는 공간
=> FILE_LEVEL 은 썸네일에서만 사용하는 컬럼인데 파일레벨이 1인 것만 썸네일로 사용하도록 하겠다.
▶ Board 클래스에 Attachment 변수 추가(Builder 에도 추가)
=> 썸네일 관련 항목을 저장할 목적
package com.kh.board.model.vo;
import java.sql.Date;
public class Board {
// BOARD_NO NUMBER
private int boardNo;
// BOARD_TYPE NUMBER
private int boardType;
// CATEGORY_NO NUMBER
private int categoryNo;
// BOARD_TITLE VARCHAR2(100 BYTE)
private String boardTitle;
// BOARD_CONTENT VARCHAR2(4000 BYTE)
private String boardContent;
// BOARD_WRITER NUMBER
private String boardWriter;
// 쿼리문으로 join시에는 회원번호를 활용하여 join할 것이고,
// 조회결과 작성한 사용자의 이름 or id를 저장하기 위한 필드
// COUNT NUMBER
private int count;
// CREATE_DATE DATE
private Date createDate;
// STATUS VARCHAR2(1 BYTE)
private String status;
private String categoryName; // Board테이블에는 존재하지 않는 칼럼
// DB에 Category 테이블에도 CATEGORY_NO가 있기 때문에 하나 생성 해둠
public Attachment attachment;
public Board() {
}
public static class Builder {
private int boardNo;
private int boardType;
private int categoryNo;
private String boardTitle;
private String boardContent;
private String boardWriter;
private int count;
private Date createDate;
private String status;
private String categoryName; // Board테이블에는 존재하지 않는 칼럼
private Attachment attachment;
public Board bulid() {
// 빌더에 초기화한 값을 그대로 Builder로 반환시켜줌
// Board 타입 객체로 모두 옮겨놓음
Board b = new Board();
b.boardNo = boardNo;
b.boardType = boardType;
b.categoryNo = categoryNo;
b.boardTitle = boardTitle;
b.boardContent = boardContent;
b.boardWriter = boardWriter;
b.count = count;
b.createDate = createDate;
b.status = status;
b.categoryName = categoryName;
b.attachment = attachment;
return b;
}
public Builder boardNo(int boardNo) {
this.boardNo = boardNo;
return this;
}
public Builder boardType(int boardType) {
this.boardType = boardType;
return this;
}
public Builder categoryNo(int categoryNo) {
this.categoryNo = categoryNo;
return this;
}
public Builder boardTitle(String boardTitle) {
this.boardTitle = boardTitle;
return this;
}
public Builder boardContent(String boardContent) {
this.boardContent = boardContent;
return this;
}
public Builder boardWriter(String boardWriter) {
this.boardWriter = boardWriter;
return this;
}
public Builder count(int count) {
this.count = count;
return this;
}
public Builder createDate(Date createDate) {
this.createDate = createDate;
return this;
}
public Builder status(String status) {
this.status = status;
return this;
}
public Builder categoryName(String categoryName) {
this.categoryName = categoryName;
return this;
}
public Builder attachment(Attachment attachment) {
this.attachment = attachment;
return this;
}
}
// 똑같이 한 이유는 /...?
@Override
public String toString() {
return "Board [boardNo=" + boardNo + ", boardType=" + boardType + ", categoryNo=" + categoryNo + ", boardTitle="
+ boardTitle + ", boardContent=" + boardContent + ", boardWriter=" + boardWriter + ", count=" + count
+ ", createDate=" + createDate + ", status=" + status + ", categoryName=" + categoryName
+ ", attachment=" + attachment + "]";
}
public int getBoardNo() {
return boardNo;
}
public void setBoardNo(int boardNo) {
this.boardNo = boardNo;
}
public int getBoardType() {
return boardType;
}
public void setBoardType(int boardType) {
this.boardType = boardType;
}
public int getCategoryNo() {
return categoryNo;
}
public void setCategoryNo(int categoryNo) {
this.categoryNo = categoryNo;
}
public String getBoardTitle() {
return boardTitle;
}
public void setBoardTitle(String boardTitle) {
this.boardTitle = boardTitle;
}
public String getBoardContent() {
return boardContent;
}
public void setBoardContent(String boardContent) {
this.boardContent = boardContent;
}
public String getBoardWriter() {
return boardWriter;
}
public void setBoardWriter(String boardWriter) {
this.boardWriter = boardWriter;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public Attachment getAttachment() {
return attachment;
}
public void setAttachment(Attachment attachment) {
this.attachment = attachment;
}
}
▶ board-mapper.xml 에 사진게시판 썸네일 list를 가져오는 쿼리문 작성
▶ ThumbnailListController.java
package com.kh.board.controller;
import java.io.IOException;
import java.util.ArrayList;
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 com.kh.board.model.service.BoardService;
import com.kh.board.model.vo.Board;
/**
* Servlet implementation class ThumbnailListController
*/
@WebServlet("/list.th")
public class ThumbnailListController extends HttpServlet {
private static final long serialVersionUID = 1L;
public ThumbnailListController() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 사진게시판에 리스트에 필요한 데이터 조회
// 게시판(board)정보와 썸네일(Attachment)정보
ArrayList<Board> list = new BoardService().selectThumbnailList();
request.setAttribute("list", list);
request.getRequestDispatcher("views/board/thumbnailListView.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
▶ BoardService.java
▶ BoardDao.java
2. 사진게시판 작성하는 폼 만들기
▶ thumbnailEnrollForm.jsp
<%@ 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>
</head>
<style>
#enroll-form>table{border:1px solid white;}
#enroll-form input, #enroll-form textarea{
width:100%;
box-sizing:border-box;
}
</style>
<body>
<%@ include file="../common/menubar.jsp" %>
<div class="outer">
<br>
<h2 align="center">사진게시판 작성</h2>
<br>
<form action="<%=contextPath %>/insert.th" method="post"
id="enroll-form" enctype="multipart/form-data">
<!-- 현재 로그인한 사용자의 회원번호 전송 -->
<input type="hidden" name="userNo" value="<%= loginUser.getUserNo() %>">
<table align="center">
<tr>
<th width="100">제목</th>
<td colspan="3"><input type="text" name="boardTitle" required></td>
</tr>
<tr>
<th width="100">내용</th>
<td colspan="3">
<textarea name="boardContent" style="resize:none;" rows="5" required></textarea>
</td>
</tr>
<tr>
<!-- 썸네일로 등록될 영역 -->
<th width="100">대표이미지</th>
<td colspan="3" align="center">
<img id="contentImg0" width='250' height='170'>
</td>
</tr>
<tr>
<!-- 현재이미지를 타고들어갔을 때 상세이미지 -->
<th width="100">상세이미지</th>
<td>
<img id="contentImg1" width='150' height='120'>
</td>
<td>
<img id="contentImg2" width='150' height='120'>
</td>
<td>
<img id="contentImg3" width='150' height='120'>
</td>
</tr>
</table>
<!-- id가 contentImg1 클릭하면 file0인 것 클릭, contentImg2 클릭하면 file1인 것 클릭되도록 설정 -->
<div id="file-area">
<input type="file" id="file0" name="file0" required>
<input type="file" id="file1" name="file1">
<input type="file" id="file2" name="file2">
<input type="file" id="file3" name="file3">
</div>
<script>
$(function(){
// 첨부파일 선택 숨기기
$("#file-area").hide();
// $("#contentImg0").click(() => $("#file1").click());
/* id가 contentImg로 시작하는 img태그를 모두 가져오겠다 */
$("img[id^=contentImg]").each(function(index, value) {
$(value).click(function(){ // contextImg1을 클릭하게되면(value=>contentImg1~3) file0 클릭되도록 반복문 수행
$("#file"+index).click();
});
});
$("input[type=file]").each(function(index, value) {
$(value).change(function(){loadImg(value,index)}) ;
//loadImg(value,index) 하게되면 제대로 호출이 안돼서 익명함수로 묶어줌
})
})
// 미리보기 이벤트
function loadImg(file,index){
// file : 현재 변화가 생긴 input type="file" 요소 객체
// index : 몇번째 file에 변화가 발생했는지 확인 후 그 영역에 미리보기를 해주기 위한 변수
console.log(file.files[0]); // 파일명
console.dir(file); // input#file0~4
if(file.files[0]){
// 선택된 파일이 존재할 경우
// 존재하지 않는다면 undefind반환
// 파일을 읽어들일 FileReader 객체 생성
const reader = new FileReader();
// 파일을 읽어들일 수 있는 메소드
// readAsDataURL(파일) => 파일을 읽어들이는 순간 해당 파일만의
// 고유한 URL이 부여됨 => 미리보기로 현재 부여된 url을 src속성값으로 추가
reader.readAsDataURL(file.files[0]);
// 파일 읽기가 완료되었을 때 실행할 함수 정의
reader.onload = function(e){
// e == event
// event.target.result에 각 파일의 고유한 url 값이 담긴다.
$("#contentImg"+index).attr("src",e.target.result); // 추가하고자하는 src의 url 값 추가
}
}else {
// 선택했던 파일이 사라졌을 경우. 파일선택 클릭후 취소버튼 눌렀을 때
$('#contentImg'+index).removeAttr("src"); // src 속성 제거. url 제거한다.
}
}
</script>
<br>
<div align="center">
<button>등록</button>
</div>
</form>
</div>
</body>
</html>
- readAsDataURL(파일) => 파일을 읽어들이는 순간 해당 파일만의 고유한 URL이 부여된다. 미리보기로 현재 부여된 url을 src 속성값으로 추가
- 파일선택을 클릭하여 파일을 추가하게되면(바뀌게 되면) fuction loadImg 함수 실행
$("input[type=file]").each(function(index, value) { $(value).change(function(){loadImg(value,index)}) ; //loadImg(value,index) 하게되면 제대로 호출이 안돼서 익명함수로 묶어줌 }) |
- file.files[0] => list에 index가 하나라도 추가되면(첨부된 파일이 있다면) 그 값을 가져온다.(파일첨부에는 각각 하나의 파일밖에 못가져오니까 files[0] 임
▶ ThumbnailInsertController.java
package com.kh.board.controller;
import java.io.IOException;
import java.util.ArrayList;
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.board.model.service.BoardService;
import com.kh.board.model.vo.Attachment;
import com.kh.board.model.vo.Board;
import com.kh.common.MyFileRenamePolicy;
import com.oreilly.servlet.MultipartRequest;
/**
* Servlet implementation class ThumbnailInsertController
*/
@WebServlet("/insert.th")
public class ThumbnailInsertController extends HttpServlet {
private static final long serialVersionUID = 1L;
public ThumbnailInsertController() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("views/board/thumbnailEnrollForm.jsp").forward(request, response);
}
// 등록기능이 들어갈 예정
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
if(ServletFileUpload.isMultipartContent(request)) {
int maxSize = 20 * 1024 * 1024; // 20mbyte
// 사진 저장할 파일의 물리적인 경로
String savePath = request.getSession().getServletContext().getRealPath("/resources/thumbnail_upfiles/");
// 절대경로를 얻어옴
MultipartRequest multi = new MultipartRequest(request, savePath, maxSize, "UTF-8", new MyFileRenamePolicy());
// DB에 전달할 데이터 추출
// BOARD - 게시글 작성자, 제목, 내용
Board b = new Board.Builder()
.boardWriter(multi.getParameter("userNo"))
.boardTitle(multi.getParameter("boardTitle"))
.boardContent(multi.getParameter("boardContent"))
.bulid();
// ATTACHMENT 테이블에 여러번 insert할 데이터 뽑기(최소 1번 이상)
ArrayList<Attachment> list = new ArrayList();
for(int i=0; i<4; i++) { // 4회 반복
// file0, file1, file2, file3 => name 속성값
String key = "file"+i;
if(multi.getOriginalFileName(key) != null) {
// 첨부파일이 있는 케이스
// Attachment 객체 생성 + 원본명, 수정명, 저장경로, 파일레벨 담아줄 예정
Attachment at = new Attachment();
at.setOriginName(multi.getOriginalFileName(key));
at.setChangeName(multi.getFilesystemName(key));
// file0으로 넘어온 데이터가 실제 웹사이트에 저장된 이름을 반환해줌
at.setFilePath("resources/thumbnail_upfiles/");
if(i == 0) {
at.setFileLevel(1); // 썸네일
}else {
at.setFileLevel(2); // 대표이미지로 설정 X
}
list.add(at);
}
}
int result = new BoardService().insertThumbnailBoard(b,list);
if(result > 0) {
// 성공시에는 list.th 재요청
request.getSession().setAttribute("alertMsg", "업로드 완료");
response.sendRedirect("list.th"); // 상대경로
}else {
request.setAttribute("errorMsg", "업로드 실패");
request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
}
}
}
}
▶ BoardService.java
▶ board-mapper.xml
▶ BoardDao.java
3. 사진게시판 상세보기
■ thumbnailDetailView.java
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="com.kh.board.model.vo.*, java.util.ArrayList"%>
<%
Board b = (Board) request.getAttribute("b");
ArrayList<Attachment> list = (ArrayList<Attachment>) request.getAttribute("list");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%@ include file="../common/menubar.jsp" %>
<div class="outer">
<br>
<h2 align="center">사진게시판 상세보기</h2>
<br>
<table class="detail-area" align="center">
<tr>
<td width="70">제목</td>
<td colspan="3" width="600"><%= b.getBoardTitle() %></td>
</tr>
<tr>
<td>작성자</td>
<td><%= b.getBoardWriter() %></td>
<td>작성일</td>
<td><%= b.getCreateDate() %></td>
</tr>
<tr>
<td>내용</td>
<td colspan="3">
<p style="height:50px;"><%= b.getBoardContent() %></p>
</td>
</tr>
<tr>
<td>대표사진</td>
<td colspan="3">
<div>
<img src="<%= contextPath %>/<%= list.get(0).getFilePath() + list.get(0).getChangeName() %>"
width="500" height="300">
<!-- list.get(0) => 대표사진 -->
</div>
</td>
</tr>
<tr>
<td>상세사진</td>
<td colspan="3">
<% for(int i=1; i<list.size(); i++) { %>
<img src="<%= contextPath %>/<%= list.get(i).getFilePath() + list.get(i).getChangeName() %>"
width="200" height="150">
<% } %>
<!-- 등록한 상세이미지 만큼만 반복적으로 사진 추가됨 -->
</td>
</tr>
</table>
</div>
</body>
</html>
■ thumbnailListView.java
<script>
$(function(){
$(".thumbnail").click(function(){
// 자식 요소들 중 하나를 가져옴
location.href = "<%= contextPath%>/detail.th?bno="+$(this).children().eq(0).val();
})
}
</script>
▶ 우리는 5-1. 게시판 만들기에서 사용하였던 SQL "selectAttachment"와 "selectBoard"를 이용하겠다.
▶ ThumbnailDetailController.java
package com.kh.board.controller;
import java.io.IOException;
import java.util.ArrayList;
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 com.kh.board.model.service.BoardService;
import com.kh.board.model.vo.Attachment;
import com.kh.board.model.vo.Board;
/**
* Servlet implementation class ThumbnailDetailController
*/
@WebServlet("/detail.th")
public class ThumbnailDetailController extends HttpServlet {
private static final long serialVersionUID = 1L;
public ThumbnailDetailController() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int boardNo = Integer.parseInt(request.getParameter("bno"));
int result = new BoardService().increaseCount(boardNo);
// 이미 만들었던 조회수 증가서비스 이용
String url = "";
if(result > 0) {
// 게시판 번호 조회
Board b = new BoardService().selectBoard(boardNo);
// 이미지 정보 가져옴
ArrayList<Attachment> list = new BoardService().selectAttachmentList(boardNo);
request.setAttribute("b", b);
request.setAttribute("list", list);
System.out.println(b);
System.out.println(list);
url = "views/board/thumbnailDetailView.jsp";
}else {
request.setAttribute("errorMsg", "사진 게시글 조회 실패");
url = "views/common/errorPage.jsp";
}
request.getRequestDispatcher(url).forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
▶ BoardService.java
▶ BoardDao.java
'Server > JSP과 Servlet' 카테고리의 다른 글
[JSP] 6-2. AJAX (Gson ,ArrayList 받기) (0) | 2023.12.14 |
---|---|
[JSP] 6-1. AJAX 개요, get&post방식으로 서버에 데이터 전송 및 응답(ajax 통신, json) (0) | 2023.12.14 |
[JSP] 5-3. 게시판 상세 페이지 수정, 삭제 (0) | 2023.12.12 |
[JSP] 5-2. 게시판 상세 페이지 만들기(+첨부파일 업로드) (0) | 2023.12.11 |
[JSP] 5-1. 게시판 만들기(페이지) (0) | 2023.12.08 |