board-mapper.xml
1) 조회수 증가 조회
<entry key="increaseCount">
UPDATE BOARD
SET COUNT = COUNT+1
WHERE BOARD_NO = ?
AND STATUS = 'Y'
</entry>
2) 게시판 조회
<entry key="selectBoard">
SELECT BOARD_NO, CATEGORY_NAME, BOARD_TITLE, BOARD_CONTENT, USER_ID, CREATE_DATE
FROM BOARD B
LEFT JOIN CATEGORY USING (CATEGORY_NO)
JOIN MEMBER ON (BOARD_WRITER = USER_NO)
WHERE BOARD_NO = ?
AND B.STATUS = 'Y'
</entry>
3) 사진 목록 조회
<entry key="selectAttachment">
SELECT FILE_NO, ORIGIN_NAME, CHANGE_NAME, FILE_PATH
FROM ATTACHMENT
WHERE REF_BNO = ?
</entry>
BoardDao.java
1) increaseCount(boardNo)
: 조회수 조회하는 메소드
public int increaseCount(Connection conn, int boardNo) {
int result = 0;
PreparedStatement pstmt = null;
String sql = prop.getProperty("increaseCount");
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, boardNo);
result = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(pstmt);
}
return result;
}
2) selectBoard(boardNo)
: 일반 게시판에서 사용한 selectBoard() 메소드 재활용
public Board selectBoard(Connection conn, int boardNo) {
Board b = null;
PreparedStatement pstmt = null;
ResultSet rset = null;
String sql = prop.getProperty("selectBoard");
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, boardNo);
rset = pstmt.executeQuery();
if(rset.next()) {
b = new Board(rset.getInt("BOARD_NO")
, rset.getString("CATEGORY_NAME")
, rset.getString("BOARD_TITLE")
, rset.getString("BOARD_CONTENT")
, rset.getString("USER_ID")
, rset.getDate("CREATE_DATE"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(rset);
close(pstmt);
}
return b;
}
3) selectAttachmentList(boardNo)
: 사진 목록 조회하는 메소드
public ArrayList<Attachment> selectAttachmentList(Connection conn, int boardNo) {
PreparedStatement pstmt = null;
ResultSet rset = null;
String sql = prop.getProperty("selectAttachment");
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, boardNo);
rset = pstmt.executeQuery();
while(rset.next()) {
Attachment a = new Attachment();
a.setChangeName(rset.getString("CHANGE_NAME"));
a.setOriginName(rset.getString("ORIGIN_NAME"));
a.setFilePath(rset.getString("FILE_PATH"));
list.add(a);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(rset);
close(pstmt);
}
return list;
}
thumbnailDetailView.jsp
<%@ include file="/views/common/menubar.jsp"%>
<div>
<table>
<tr>
<td>제목</td>
<td colspan="3"><%=b.getBoardTitle()%></td>
</tr>
<tr>
<td>작성자</td>
<td><%=b.getBoardWriter()%></td>
<td>작성일</td>
<td><%=b.getCreateDate()%></td>
</tr>
<tr>
<td>대표이미지</td>
<td colspan="3"></td>
<div>
<img src="<%=contextPath%>/<%=list.get(0).getFilePath()+list.get(0).getChangeName()%>" width="500" height="350">
</div>
</tr>
<tr>
<td>상세이미지</td>
<td colspan="3">
<%for(int i=1; i<list.size(); i++) {%>
<img src="<%=contextPath%>/<%=list.get(0).getFilePath()+list.get(i).getChangeName()%>" width="200" height="100">
<%}%>
</td>
</tr>
</table>
</div>
thumbnailEnrollForm.jsp
1) onchange
: input 태그의 내용이 변경되었을 때 발생하는 이벤트
2) 파일 선택 버튼
① inputFile: this(버튼), 변화가 일어난 input[type:file] 요소 객체
② num: input[type:file] 요소 객체의 순서를 확인하는 매개변수 → 해당 번호로 원하는 위치에 사진을 삽입한다.
3) inputFile.files.length
① files 속성: 업로드된 파일 정보를 배열로 반환한다.
② 파일 선택: 1을 출력
③ 파일 취소: 0을 출력
4) FileReader
: 선택된 파일이 있을 때 해당 파일을 읽어 영역에 삽입하기 위해 파일을 읽어주는 FileReader 객체를 생성한다.
5) readAsDataURL(inputFile.files[0])
① 파일을 읽어들이는 메소드
② 어떤 파일을 읽을 것인지 매개변수로 전달해야 하는데 이때 파일 선택 버튼을 각각 따로 본 상태에서 해당 배열에서 0번을 읽어들인다.
③ 해당 파일을 읽어들이는 순간 해당 파일의 고유 URL에 부여되고, 해당 URL을 src 속성으로 부여한다.
6) onload = function(e){}
: 파일 읽기가 완료됐을 때 실행하는 함수
- e.target.result: 해당 URL
7) 파일 취소 시
: 사진을 없애야 하므로 url을 null로 초기화한다.
<%@ include file="/views/common/menubar.jsp"%>
<div class="outer">
<form action="<%=contextPath%>/insert.th" id="enroll-form" method="post" 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>내용</th>
<td colspan="3"><textarea name="boardContent" style="resize:none;" rows="5" required></textarea></td>
</tr>
<tr>
<th>대표이미지</th>
<td colspan="3" align="center">
<img id="titleImg" width="250" height="170">
</td>
</tr>
<tr>
<th>상세이미지</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>
<div id="file-area">
<input type="file" id="file1" onchange="loadImg(this,1);" name="file1" required>
<input type="file" id="file2" onchange="loadImg(this,2);" name="file2">
<input type="file" id="file3" onchange="loadImg(this,3);" name="file3">
<input type="file" id="file4" onchange="loadImg(this,4);" name="file4">
</div>
<div align="center">
<button>등록</button>
</div>
</form>
<script>
function loadImg(inputFile, num){
if(inputFile.files.length == 1){
var reader = new FileReader();
reader.readAsDataURL(inputFile.files[0]);
reader.onload = function(e){
switch(num){
case 1: $("#titleImg").attr("src", e.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;
}
}
} else {
switch(num){
case 1: $("#titleImg").attr("src", null); break;
case 2: $("#contentImg1").attr("src", null); break;
case 3: $("#contentImg2").attr("src", null); break;
case 4: $("#contentImg3").attr("src", null); break;
}
}
}
</script>
</div>
ThumbnailInsertController.java
1) 매핑값 insert.th (작성페이지에서 등록 버튼 클릭 시 컨트롤러)
2) ServletFileUpload.isMultipartContent(request)
: 전달된 request 객체가 multipart/form-data 형식일 때
3) int maxSize = 10*1024*1024
: 전송 용량 제한
4) request.getSession().getServletContext().getRealPath("/resources/thumbnail_upfiles/")
: 저장할 물리경로 설정
5) MultipartRequest(request, savePath, maxSize, "UTF-8", new MyFileRenamePolicy())
: 파일명 수정객체까지 등록하여 서버에 업로드
6) name값이 각각 file1~4이므로 해당 key값을 for문으로 돌려서 꺼낸다.
① 첨부파일이 있을 경우 Attachment 객체에 값을 넣고 list에 담는다.
② i이 1일 때 FileLevel을 1로 하고, 1이 아닐 때 FileLevel을 2로 놓는다.
@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.setCharacterEncoding("UTF-8");
if(ServletFileUpload.isMultipartContent(request)) {
int maxSize = 10*1024*1024;
String savePath = request.getSession().getServletContext().getRealPath("/resources/thumbnail_upfiles/");
MultipartRequest multiRequst = new MultipartRequest(request, savePath, maxSize, "UTF-8", new MyFileRenamePolicy());
Board b = new Board();
b.setBoardWriter(multiRequst.getParameter("userNo"));
b.setBoardTitle(multiRequst.getParameter("boardTitle"));
b.setBoardContent(multiRequst.getParameter("boardContent"));
ArrayList<Attachment> list = new ArrayList<>();
for(int i = 1; i <= 4; i++) {
String key = "file" + i;
if(multiRequst.getOriginalFileName(key) != null) {
Attachment a = new Attachment();
a.setOriginName(multiRequst.getOriginalFileName(key));
a.setChangeName(multiRequst.getFilesystemName(key));
a.setFilePath("resources/thumbnail_upfiles/");
if(i == 1) {
a.setFileLevel(1);
} else {
a.setFileLevel(2);
}
list.add(a);
}
}
int result = new BoardService().insertThumbnailBoard(b, list);
if(result > 0) {
request.getSession().setAttribute("alertMsg", "작성 완료되었습니다.");
response.sendRedirect(request.getContextPath()+"/list.th");
} else {
request.setAttribute("errorMsg", "사진 게시에 실패하였습니다.");
request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
board-mapper.xml
1) Board 정보 넣기
<entry key="insertThumbnailBoard">
INSERT INTO BOARD(
BOARD_NO
, BOARD_TYPE
, BOARD_TITLE
, BOARD_CONTENT
, BOARD_WRITER
)
VALUES(
SEQ_BNO.NEXTVAL
, 2
, ?
, ?
, ?
)
</entry>
2) 썸네일과 사진 넣기
<entry key="insertAttachmentList">
INSERT INTO ATTACHMENT(
FILE_NO
, REF_BNO
, ORIGIN_NAME
, CHANGE_NAME
, FILE_PATH
, FILE_LEVEL
)
VALUES(
SEQ_FNO.NEXTVAL
, SEQ_BNO.CURRVAL
, ?
, ?
, ?
, ?
)
</entry>
BoardDao.jsp
1) Board 정보 넣기
public int insertThumbnailBoard(Connection conn, Board b) {
int result = 0;
PreparedStatement pstmt = null;
String sql = prop.getProperty("insertThumbnailBoard");
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, b.getBoardTitle());
pstmt.setString(2, b.getBoardContent());
pstmt.setInt(3, Integer.parseInt(b.getBoardWriter()));
result = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(pstmt);
}
return result;
}
2) 썸네일과 사진 넣기
public int insertAttachmentList(Connection conn, ArrayList<Attachment> list) {
int result = 1;
PreparedStatement pstmt = null;
String sql = prop.getProperty("insertAttachmentList");
try {
for(Attachment a : list) {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, a.getOriginName());
pstmt.setString(2, a.getChangeName());
pstmt.setString(3, a.getFilePath());
pstmt.setInt(4, a.getFileLevel());
result *= pstmt.executeUpdate();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(pstmt);
}
return result;
}