[JSP 개발] DB연동 게시판 파일 다운로드 / 업로드 기능 구현

2023. 7. 27. 21:57·■ Web/JSP
목차
  1. 0. 목적
  2. 1.  참고
  3. 2. 프로젝트 기본 계획
  4. 3. DB 생성
  5. 4. Eclipse Web Project 생성
  6. 5. [게시글 리스트] board_list.jsp 작성
  7. 6. [신규 게시글 작성] board_new.jsp 작성
  8. 7. [신규 게시글 작성내용 전송 / 파일 업로드 / DB기록] board_new_send.jsp 작성
  9. 8. [게시글 열람 / 파일 다운로드] board_read.jsp 작성
  10. 9. 최종 작동 모습
  11. 10. 소스코드 다운로드
반응형

0. 목적

JSP와 MySQL을 JDBC드라이버를 통해 연결한 후, 파일 업로드 / 다운로드 기능이 구현된 게시판을 만들어 보도록 한다. 게시판의 기능은 글 쓰기 / 글 열람 / 파일 업로드 / 파일 다운로드의 총 4가지 기능을 구현하도록 한다. CSS는 이용하지 않고 오직 기본 HTML 템플릿만 이용하여 구성하도록 하자.

 

또한, 각 게시글마다 서로다른 파일을 업로드 할 수 있으며, 사용자가 다운로드 요청 시 해당 게시글에 업로드된 파일이 정상적으로 다운로드 되어야 한다.

 

 

 


1.  참고

▣ 개발환경

프로그램 버전
MySQL DBMS 8.0.31
Eclipse for Web Developers 2020-06
Apache Tomcat v9.0.65
J-Connector 공식 홈페이지 제공 최신 버전

 

▣ DBMS 연결환경

환경 속성
포트 3306
ID root
PW root

 

▣ 기본 세팅이 준비되지 않았다면, 아래의 링크를 참고해 조치하도록 한다.

 

[Web Tip] Eclipse 프로젝트에 Apache Tomcat 서버 설정하기

0. 목적 Eclipse 프로젝트에서 사용할 수 있는 Apache Tomcat 서버를 설정해 보도록 하자. 주로 Eclipse에서 Dynamic Web Project를 사용하는 사람들이라면, 반 필수적으로 사용해야 하는 서버이지 않을까 싶다

acredev.tistory.com

 

 

[JSP 기초] JDBC 드라이버를 이용해 DBMS와 JSP 연동하기

0. 목적 JDBC 드라이버를 이용해, JSP와 DBMS를 연동하는 방법에 대해 알아보자. DBMS라 함은, 데이터베이스 관리 시스템의 약자로 MySQL DB, Maria DB 등등이 이에 포함된다. 본 포스트에서는 DBMS의 대표적

acredev.tistory.com

 

 

 


2. 프로젝트 기본 계획

▣ Web 파일

JSP 파일명 파일 설명
board_list.jsp 게시글 리스트 출력
board_read.jsp 게시글 상세내용 출력 (파일 다운로드 기능 포함)
board_new.jsp 신규 게시글 입력 (파일 업로드 기능 포함)
board_new_send.jsp 신규 게시글 입력 (파일 업로드 기능 포함)

 

▣ Database

* num
게시글 번호로서, 게시글을 구분할 수 있게 하며 AUTO_INCREMENT 속성을 부과해 게시글 작성시마다 자동으로 +1 되어 삽입되도록 계획한다.
* title, content, date
각각 제목, 내용, 게시글 작성 날짜 정보를 저장할 수 있도록 한다. date 의 경우, DATETIME 속성을 부과하면 DB 내용 삽입 시 자동으로 현재 날짜가 입력된다.
* file_name
서버에 파일 업로드시, 업로드를 희망했던 파일의 최초 이름을 저장하도록 한다.
* file_realName
서버에 파일 업로드시, 중복된 파일명의 경우 새 이름을 붙여 파일명이 변경되게 되는데 파일의 새 이름을 저장하도록 한다.

 

▣ 자바 라이브러리 파일 다운로드

cos.jar
0.05MB

파일 다운로드 기능을 구현하기 위한 자바 라이브러리 파일이다.

 


3. DB 생성

CREATE SCHEMA `file_board` ;

우선 SCHEMA를 생성한다.

 

 

 

CREATE TABLE `file_board`.`post` (
`num` INT NOT NULL AUTO_INCREMENT,
`title` VARCHAR(20) NOT NULL,
`content` TEXT NOT NULL,
`date` DATETIME NOT NULL,
`file_name` TEXT NULL,
`file_realName` TEXT NULL,
`file_route` TEXT NULL,
PRIMARY KEY (`num`));

생성한 SCHEMA 하위로, 계획했던 대로 TABLE을 생성한다.

 

 

정상적으로 file_board.post DB가 생성되었다.

 

 

 


4. Eclipse Web Project 생성

Eclipse Dynamic Web Project를 하나 생성하고, 상기 계획했던 바와 같이 JSP 파일들을 생성하도록 한다.

 

 

 

file_board > WebContent > WEB-INF > lib 폴더에 상기 다운로드 받았던 cos.jar 자바 라이브러리 파일을 프로젝트에서 인식할 수 있게 위치시켜 준다.

 

 

 

WebContent 하위에 파일이 업로드될 폴더인 upload 폴더를 하나 생성해 준다.

 

 


5. [게시글 리스트] board_list.jsp 작성

<!-- SQL 연결을 위한 import -->
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>게시글 목록</title>
</head>
<body>
<!-- 게시글 목록 폼임을 표시 -->
<h1>게시글 목록</h1>
<%
try
{
// JDBC 드라이버 연결
Class.forName("com.mysql.jdbc.Driver");
String db_address = "jdbc:mysql://localhost:3306/file_board";
String db_username = "root";
String db_pwd = "root";
Connection connection = DriverManager.getConnection(db_address, db_username, db_pwd);
// MySQL로 전송하기 위한 쿼리문인 insertQuery 문자열 선언
String insertQuery = "SELECT * FROM file_board.post order by num desc";
// MySQL 쿼리문 실행
PreparedStatement psmt = connection.prepareStatement(insertQuery);
// 쿼리문을 전송해 받아온 정보를 result 객체에 저장
ResultSet result = psmt.executeQuery();%>
<!-- 게시글 목록을 표시할 기본 테이블 생성 -->
<table border="1">
<tr>
<td colspan="5">
<h3>게시글 제목 클릭시 상세 열람 가능</h3>
</td>
</tr>
<tr>
<td colspan="5">
<button type="button" value="신규 글 작성" onClick="location.href='board_new.jsp'">신규 글 작성</button>
</td>
</tr>
<tr>
<td>번호</td>
<td>제목</td>
<td>작성일</td>
</tr>
<%
// 받아온 정보를 입력하고, 하나씩 커서를 다음으로 넘김
while (result.next())
{%>
<tr>
<!-- 번호 <td> 아래에 DB에서 받아온 num 칼럼값 삽입 -->
<td><%=result.getInt("num") %></td>
<!-- 제목 <td> 아래에 DB에서 받아온 title 칼럼값 삽입, 제목 클릭시 board_read.jsp로 연결되며 num 칼럼값을 parameter로 넘김 -->
<td><a href="board_read.jsp?num=<%=result.getInt("num") %>"><%=result.getString("title") %></a></td>
<!-- 작성일 <td> 아래에 DB에서 받아온 date 칼럼값 삽입 -->
<td><%=result.getTimestamp("date") %></td>
</tr>
<%
}%>
</table>
<%
}
catch (Exception ex)
{
out.println("오류가 발생했습니다. 오류 메시지 : " + ex.getMessage());
}%>
</body>
</html>

DB에 기록된 게시글 내용들을 불러올 수 있는 코드 내용이다. 글 제목을 클릭하면, 게시글의 상세 내용을 읽을 수 있도록 코드를 작성했다. 신규 글 작성 버튼을 누르면, board_new.jsp 로 연결되어 신규 게시글을 작성할 수 있는 페이지로 이동한다.

 

▣ 임시 실행 화면

더보기

6. [신규 게시글 작성] board_new.jsp 작성

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>신규 게시글 작성</title>
</head>
<body>
<!-- 게시글 작성 폼임을 표시 -->
<h1>게시글 작성</h1>
<!-- 파일 전송을 위한 multipart 선언 -->
<form method="post" action="board_new_send.jsp" enctype="multipart/form-data">
<table>
<tr>
<td><input type="text" placeholder="제목" name="title" maxlength="20" value=""></td>
</tr>
<tr>
<td><textarea placeholder="내용" name="content" maxlength="2048" style="height:150px;"></textarea></td>
</tr>
</table>
<input type="file" name="file">
<hr>
<input type="submit" value="글쓰기">
</form>
</body>
</html>

파일 전송 기능을 수행하기 위해 <form>의 method를 post로 설정하고, enctype 속성을 multipart/form-data로 선언해 주었다. multipart/form-data는 JSP에서 파일 전송 등의 동작을 수행하기 위해 사용되는 속성값이다.

 

 

▣ 임시 실행 화면

더보기

 

 

 


7. [신규 게시글 작성내용 전송 / 파일 업로드 / DB기록] board_new_send.jsp 작성

<%@page import="java.sql.*"%>
<%@ page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy" %>
<%@ page import="com.oreilly.servlet.MultipartRequest" %>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<%
try
{
// JDBC 드라이버 연결
Class.forName("com.mysql.jdbc.Driver");
String db_address = "jdbc:mysql://127.0.0.1:3306/file_board";
String db_username = "root";
String db_pwd = "root";
Connection connection = DriverManager.getConnection(db_address, db_username, db_pwd);
// 인코딩 UTF-8 설정
request.setCharacterEncoding("UTF-8");
// 게시글 번호를 결정하기 위한 임시 정수형 변수 선언
int num = 0;
// 절대경로를 파악하기 위한 문자열 변수 선언
String uploadRoute = "";
// MySQL로 전송하기 위한 쿼리문인 insertQuery 문자열 선언 (현재 등록된 게시글의 갯수를 파악)
String insertQuery = "SELECT MAX(num) from file_board.post";
// SQL 쿼리문을 실행 (MySQL로 전송)하기 위한 객체 선언
PreparedStatement psmt = connection.prepareStatement(insertQuery);
// 조회된 결과물들을 저장하기 위한 ResultSet 객체 선언
ResultSet result = psmt.executeQuery();
// 받아온 정보가 있을때
while(result.next())
{
// 앞서 임시 선언한 num 변수에, 가져온 MAX(num) 칼럼값 + 1을 하여 저장
num = result.getInt("MAX(num)") + 1;
}
// 날짜
Timestamp today_date = new Timestamp(System.currentTimeMillis());
String uploadDir = this.getClass().getResource("").getPath();
// 파일이 업로드될 경로
uploadRoute = "file_board/WebContent/upload/";
uploadDir = uploadDir.substring(1, uploadDir.indexOf(".metadata")) + uploadRoute;
// 파일 크기 제한 byte 크기
int maxSize = 100 * 1024 * 1024;
// 인코딩 설정
String encoding = "UTF-8";
// Multipartrequest 객체 선언
MultipartRequest multipartRequest = new MultipartRequest(request, uploadDir, maxSize, encoding, new DefaultFileRenamePolicy());
String fileName = multipartRequest.getOriginalFileName("file");
String fileRealName = multipartRequest.getFilesystemName("file");
String title = multipartRequest.getParameter("title");
String content = multipartRequest.getParameter("content");
// MySQL로 전송하기 위한 쿼리문인 insertQuery 문자열 선언 (사용자가 신규 게시글 작성한 정보를 전송)
insertQuery = "INSERT INTO file_board.post(num, title, content, date, file_name, file_realName, file_route) VALUES (?, ?, ?, ?, ?, ?, ?)";
// SQL 쿼리문을, 새로운 내용을 토대로 재실행
psmt = connection.prepareStatement(insertQuery);
// VALUES ? 값에 하나씩 삽입하여 전송
psmt.setInt(1, num);
psmt.setString(2, title);
psmt.setString(3, content);
psmt.setTimestamp(4, today_date);
psmt.setString(5, fileName);
psmt.setString(6, fileRealName);
psmt.setString(7, "/file_board/upload/" + fileRealName);
// INSERT 하여 반영된 레코드의 건수결과를 반환
psmt.executeUpdate();
// 게시글 목록으로 redirect
response.sendRedirect("board_list.jsp");
}
catch (Exception ex)
{
out.println("오류가 발생했습니다. 오류 메시지 : " + ex.getMessage());
}
%>

파일 업로드를 구현하기 위한 MultipartRequest의 실행 로직이다.

 

MultipartRequest의 객체를 선언하며 인자값은 아래와 같이 부여했다.

 

인자값 지정
HttpServletRequest request
업로드된 파일이 저장될 위치 uploadDir
(* 본 프로젝트에서는 \file_board\upload)
파일 제한 최대 크기 100 * 1024 * 1024
파일 인코딩 UTF-8
FileRenamePolicy (동일 파일명 처리 방식) new DefaultFileRenamePolicy()

new DefaultFileRenamePolicy() 는, test.txt 파일을 업로드 할 시 동일한 파일명이 존재한다면 test1.txt 로 숫자를 붙여 파일을 저장하는 것을 의미한다.

 

서버에 파일을 전송하고 저장하기 위해서는 WebContent 폴더를 인식시켜야 한다.

 

하지만, 서버에서 파일을 내려받을 경로에서는, 즉 DB에 route를 저장할 때에는 WebContent 폴더 경로를 생략해야만 다운로드 링크가 작동된다. 이에 유의하도록 하자.

 

 

 


8. [게시글 열람 / 파일 다운로드] board_read.jsp 작성

<%@page import="java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시글 열람</title>
</head>
<body>
<%
try
{
//JDBC 드라이버 연결
Class.forName("com.mysql.jdbc.Driver");
String db_address = "jdbc:mysql://127.0.0.1:3306/file_board";
String db_username = "root";
String db_pwd = "root";
Connection connection = DriverManager.getConnection(db_address, db_username, db_pwd);
// 문자열 인코딩 설정
request.setCharacterEncoding("UTF-8");
// 파라미터값을 통해 넘어온 게시글 번호를 문자열 변수에 저장
String num = request.getParameter("num");
// DB에 전송할 쿼리문 설정
String insertQuery = "SELECT * FROM file_board.post WHERE num=" + num;
// 쿼리문 실행
PreparedStatement psmt = connection.prepareStatement(insertQuery);
// 받아온 정보를 result 객체에 저장
ResultSet result = psmt.executeQuery();%>
<table border="1">
<%
// 받아온 정보가 있다면...
while(result.next())
{%>
<tbody>
<tr>
<td style="width: 20%;">글 제목</td>
<td colspan="2"><%=result.getString("title") %></td>
</tr>
<tr>
<td>작성 일자</td>
<td colspan="2"><%=result.getTimestamp("date") %></td>
</tr>
<tr>
<td>내용</td>
<td colspan="2" style="height: 200px; text-align: left;"><%=result.getString("content") %></td>
</tr>
<tr>
<td>첨부파일</td>
<td colspan="2">
<%
// 만약, 첨부파일이 null 이라면... == 첨부파일이 없는 것
if (result.getString("file_route").equals("/file_board/upload/null"))
{%>
첨부파일이 없습니다.
<%
}
else
{%>
<a style="color: blue; text-decoration: underline;" href="<%=result.getString("file_route") %>"><%=result.getString("file_realName") %></a>
<%
}%>
</td>
</tr>
</tbody>
</table>
<%} %>
<a href="board_list.jsp">목록</a>
<%
}
catch(Exception ex)
{
out.print(ex.getMessage());
}%>
</body>
</html>

게시글을 열람하기 위한 코드를 작성했다.

 

첨부파일이 없다면, DB에 저장된 file_route 의 경로가 /file_board/upload/null 일 것이다. 이를 판별해서, 게시글에 첨부파일이 있는지 없는지 여부를 판단할 수 있는 로직을 구현했다.

 

첨부파일이 있을 경우, 파일명이 출력되며 클릭 시 다운로드가 이루어진다.

첨부파일이 없을 경우, 첨부파일이 없습니다. 라는 문구가 출력된다.

 

▣ 임시 실행 화면 (첨부파일이 없을 경우)

더보기

▣ 임시 실행 화면 (첨부파일이 있을 경우)

더보기

 

 

 


9. 최종 작동 모습

 

 

 


10. 소스코드 다운로드

file_board.zip
3.84MB

상기 폴더를 내려받아 Eclipse 프로젝트에 적용시키면 된다.

 

 

 

 

blog_JSP_ex/file_board at main · acredev/blog_JSP_ex

Contribute to acredev/blog_JSP_ex development by creating an account on GitHub.

github.com

동시에, 본 소스코드는 필자의 GitHub에서도 다운로드가 제공된다. 상기 링크를 참고하여 다운로드 받을 수 있다.

 

 

300x250
반응형
저작자표시 비영리 변경금지 (새창열림)
  1. 0. 목적
  2. 1.  참고
  3. 2. 프로젝트 기본 계획
  4. 3. DB 생성
  5. 4. Eclipse Web Project 생성
  6. 5. [게시글 리스트] board_list.jsp 작성
  7. 6. [신규 게시글 작성] board_new.jsp 작성
  8. 7. [신규 게시글 작성내용 전송 / 파일 업로드 / DB기록] board_new_send.jsp 작성
  9. 8. [게시글 열람 / 파일 다운로드] board_read.jsp 작성
  10. 9. 최종 작동 모습
  11. 10. 소스코드 다운로드
'■ Web/JSP' 카테고리의 다른 글
  • [JSP 개발] MySQL DB 연동: 간단한 JSP 게시판 만들기 (글 쓰기 / 열람 / 수정 / 삭제)
  • [JSP 기초] JDBC 드라이버를 이용해 DBMS와 JSP 연동하기
Min Hyuk-Lee
Min Hyuk-Lee
시스템 엔지니어로 근무하고 있습니다.
아크레의 개발로그시스템 엔지니어로 근무하고 있습니다.
  • Min Hyuk-Lee
    아크레의 개발로그
    Min Hyuk-Lee
    m_file@naver.com
  • 전체
    오늘
    어제
    • 📝 Log. (81)
      • ■ Dev. Language (11)
        • C (5)
        • C# (6)
      • ■ Dev. ETC (8)
        • Unity 3D (3)
        • Android Studio (JAVA) (5)
      • ■ Web (6)
        • HTML (3)
        • JSP (3)
      • ■ Linux (8)
        • Shell (2)
        • Linux Tip. (6)
        • 보안취약점 진단 (0)
      • ■ Windows (4)
        • Server (1)
        • Windows Tip. (3)
      • ■ VM (1)
        • VMWare (1)
        • Virtual Box (0)
      • ■ Database (9)
        • MySQL (7)
        • OracleDB (2)
      • ■ DevKit (5)
        • IDE (4)
        • Tool (1)
      • ■ Error (17)
        • Linux 오류해결 (4)
        • DB 오류해결 (3)
        • IDE 오류해결 (2)
        • VM 오류해결 (3)
        • Unity 오류해결 (4)
        • SSH, SFTP 오류해결 (1)
      • ■ Photoshop (3)
        • 디자인&이미지 창작 (3)
      • ■ Document (3)
        • MS Word (2)
        • PDF (1)
      • ■ Study (4)
        • Baekjoon (4)
      • ■ 작문 (1)
        • 회고 (1)
      • ■ ETC (1)
        • Car (0)
        • etc (1)
  • 🌐 Menu

    • 📓 Guestbook
  • 🔗 Other Links

    • GitHub
    • 아크레의 IT ISSUE
  • 📢 Notice

    • [스킨 업데이트] hELLO v4.10.0 적용완료
    • [스킨 업데이트] hELLO v4.9.0 적용 완료
    • [스킨 업데이트] hELLO v4.8.1 적용 완료
  • 💬 Recent Comments

  • hELLO· Designed By정상우.v4.10.0
Min Hyuk-Lee
[JSP 개발] DB연동 게시판 파일 다운로드 / 업로드 기능 구현

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.