JSP - 간단한 게시판 구현하기(6) - 게시물 작성하기 및 첨부파일 (2022-09-29)
1. 서론
드디어 여러분들이 기다리던 그 시간이다.
이제 게시글 목록도 보이고 그 중 하나를 클릭하면 게시물의 상세정보도 보이니
이제 게시물 작성을 해보도록 하자.
근데 첨부파일을 곁들인....
2. 본론
일단 밑작업부터 해야 하는데
먼저 cos.jar부터 다운로드 받도록 하자.
필자는 부트캠프에서 업로드 한 것을 다운로드 받았다(이것이 부, 명예...명성...)
개인적으로 cos를 다운로드 받으려면
Servlets.com
Home What's New? COS File Upload Library Servlet Polls Mailing Lists Servlet Engines Servlet ISPs Servlet Tools Documentation Online Articles The Soapbox "Java Servlet Programming, Second Edition" "Java Enterprise Best Practices" Speaking & Slides About Ja
www.servlets.com
위 링크를 타고 홈페이지에 들어간다.
COS File Upload Library를 클릭하면
아래쪽 언저리에 이렇게 다운로드 받을 수 있으니 참고 바란다.
어쨋든 다운 받았으면
해당 프로젝트 파일 → wepapp하위 → WEB-INF 하위 → lib 폴더에 넣어주면 된다.
이제 밑작업도 끝났으니 전체 코드를 보자.
boardWrite(전체코드)
<%@ page language="java" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>boardWrite</title>
</head>
<body>
<%@ include file="header.jsp"%>
<div align="center">
<form action="boardWriteService.jsp" method='post'
enctype="multipart/form-data">
<table border=1>
<caption>
<font size="5"><b>게시글 등록</b></font>
</caption>
<tr>
<th width="100px">제목</th>
<td><input style="width: 96%;" type="text" name="title"></td>
</tr>
<tr>
<th>내용</th>
<td><textarea style="width: 98%;" rows="10" cols="30" name="content"></textarea></td>
</tr>
<tr>
<th>파일첨부</th>
<td><input type="file" name="upfile"></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="글쓰기">
<input type="button" value="목록" onclick="history.back();">
</td>
</tr>
</table>
</form>
</div>
<%@ include file="footer.jsp"%>
</body>
</html>
블럭 놀이 하듯 가볍게 게시글을 작성할 수 있는 페이지를 만들자. 이건 어렵지 않다.
단, 여기서 중요한 코드 하나가 있다.
<form action="boardWriteService.jsp" method='post'
enctype="multipart/form-data">
<!-- enctype="multipart/form-data"는
enctype을 지정함으로서 '나는 파일을 전송할 거야' 라는 것을 jsp에게
알려주는 것이며,
한번에 많은 데이터를 전송하기 위해 사용되는 코드이다.
전송해야할 데이터가 커서 하나의 데이터로 전송할 수가 없을때,
데이터를 분할하여 전송해야함을 명시하는 것.
WEB-INF/lib 에 있는 cos.jar 파일의 기능을 이용하는 것이다.
-->
boardWriteService(전체코드)
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@page import="com.oreilly.servlet.multipart.FileRenamePolicy"%>
<%@page import="session_quiz.BoardDAO"%>
<%@page import="java.text.SimpleDateFormat"%>
<%@page import="java.util.Date"%>
<%@page import="session_quiz.BoardDTO"%>
<%@page import="java.io.File"%>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
/*
enctype="multipart/form-data" 를 이용했을 때에는 아래의 코드로 데이터를 받아올 수 없다.
왜인지는 모르니 그냥 받아들여라.
String title = request.getParameter("title");
String content = request.getParameter("content");
String upfile = request.getParameter("upfile");
out.print("제목 : " + title + "<br>");
out.print("내용 : " + content + "<br>");
out.print("파일명 : " + upfile + "<br>");
*/
/*
파일의 용량 단위
1bit
8bit == 1byte
1024byte == 1kb
1024kb = 1mb
1024mb = 1gb
*/
String id = (String)session.getAttribute("id"); //로그인의 id 세션값을 받아옴.
//만약에 세션에 아이디가 없을 때(공백도 아닌)
if(id == null){
//그러면 login.jsp로 보낸다.
response.sendRedirect("login.jsp");
return;
}
//로컬 디스크(C:)에 javas폴더에 upload폴더 안에 id에 해당하는 폴더를 자동 생성
//보통 기본 경로는 C:\javas\upload\ 이거 이지만 역슬래시를 한개 더 주어
//경로에 대한 문자열이라는 것을 표현
String saveDir = "C:\\javas\\upload\\" + id;
File file = new File(saveDir); //saveDir에 File을 찾아갈 수 있는 권한을 부여.
if(file.exists() == false) // 폴더 또는 파일의 존재유무확인(있으면 true 없으면 false)
file.mkdir(); // 폴더 or 디렉토리 생성하는 메서드
// 10MB 사용할 maxPostSize의 선언 // 1024 바이트 * 1024 -> 1키로바이트 * 1024 -> 1메가바이트
int maxPostSize = 1024 * 1024 * 10;
//단위가 없으면 byte가 기본 단위로 저장된다.
MultipartRequest multi = new MultipartRequest(request, saveDir, maxPostSize, "UTF-8", new DefaultFileRenamePolicy());
/*
마지막 매개변수로 new DefaultFileRenamePolicy() 를 입력하면
중복 파일이 있을 시에는 파일 이름 끝에 1을 붙여서 저장한다.
위의 매개변수를 입력하지 않으면 같은 이름의 파일이 있을 시에는 덮어쓴다.
*/
/boardWrite에서 입력값을 받아온다.
String title = multi.getParameter("title");
String content = multi.getParameter("content");
String originFileName = multi.getOriginalFileName("upfile");
String systemFileName = multi.getFilesystemName("upfile"); // new DefaultFileRenamePolicy()
/*
여담이지만 multi.getOriginalFileName과 multi.getFilesystemName차이점은
multi.getOriginalFileName은 유저가 올린 파일명을 그대로 얻어오는 함수이다.
multi.getFilesystemName MultipartRequest모듈 내부에서 업로드한 파일명을 얻어오는 함수이다.
즉, 유저가 같은 이름의 파일을 또 올리면 MultipartRequest모듈이 내부로직으로 겹치는 파일명을
수정해주는데 그 수정된 이름을 파일명으로 받는다.
근데.. 더 실험은 해봐야겠지만 지금은 둘이 별차이 없다...
*/
//만약 제목이나 내용이 비어있다면
if(title.isEmpty() || content.isEmpty() ){
다음 alert창을 띄우고 뒤로 보낸다.
out.print("<script>alert('제목과 내용을 입력하세요.'); history.back();</script>");
return;
}
//DTO클래스를 board변수로 새로운 DTO클래스 선언
BoardDTO board = new BoardDTO();
//boardWrite에서 받아온 값들을 DTO에 저장
board.setId(id);
board.setTitle(title);
board.setContent(content);
board.setFileName(originFileName);
board.setHit(0);
//작성일은 따로 인코딩하여서
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String writeTime = sdf.format(date);
//DTO에 저장한다.
board.setWriteTime(writeTime);
//DAO클래스를 boardDao로 새로운 DAO클래스 선언
BoardDAO boardDao = new BoardDAO();
//DAO에 boardWrite메서드를 호출하여 DTO의 저장된 값을 전달
boardDao.boardWrite(board);
//그 후 DB연결 끊기
boardDao.disconnection();
%>
//일련의 과정이 정상적으로 진행되었으면 alert창을 띄우고 boardForm으로 돌아간다.
<script>alert('게시글 작성 완료'); location.href='boardForm.jsp';</script>
모든 코드를 작성 완료 했으니 게시글 하나만 적어보자.
이렇게 작성하고 글쓰기를 버튼을 클릭하면?
띠용??? 웨 에러가 나지?
근본 원인을 읽어보니 대충 설정했던 경로가 존재하지 않아서 오류가 난 듯 하다.
그래서 설정 경로대로 폴더를 만들어 준다.
단, upload 폴더 까지만 만들어 주었다. 어차피 일련의 과정 거치면서 알아서 유저아이디로 폴더 하나가 만들어질 것이다.
근데 신기하네....
파일 첨부를 안했음에도 불구하고 경로지정을 해야하는 것이....
어쨋든 다시 글을 쓰고 버튼을 클릭하면
alert창이 뜨는 것을 확인 할 수 있다.
게시글도 제대로 나왔다.
3. 결론
게시판이란 놈도 서버가 관여하기 시작하니 생각보다 복잡하다.
물론 코드 사용은 거의 비슷하긴 한데,,,,이제 남은 것은 게시물의 수정과 삭제이다.