홈페이지 - 파일업로드
Multipart 요청 방식일 경우의 수신 코드
( 지금은 1. cos.jar 사용 / 2. apache-commons-fileupload 스프링때 사용)
1. cos.jar 라이브러리를 이용하여 파일 업로드 및 저장을 수행
- 장점 : 편하고 코드가 비교적 간단하다.
- 단점 : 파일을 같은 이름으로 1개만 수신할 수 있다.
2. apache-commons-fileupload 라이브러리를 이용하여 파일 업로드 및 저장을 수행
- 장점 : 같은 이름으로 다중 선택하여 전송되는 파일을 처리할 수 있다.
- 단점 : 코드가 상대적으로 복잡하다.
http://www.servlets.com/cos/ 에서 cos-20.08.zip 다운로드 한다
-> cos.jar를 WEB-INF -> lib에 등록한다
[파일 업로드 페이지]
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<h2>POST방식 업로드 테스트(2) - 멀티파트 방식</h2>
<form action="test14.jsp" method="post" enctype="multipart/form-data">
<input type="file" name="attach" accept=".jpg, .png, .gif">
<input type="submit" value="업로드">
</form>
[ 파일 업로드 처리 페이지 ]
cos.jar에서는 MultipartRequest라는 클래스를 제공하며 이를 통해 multipart 요청을 처리
= multipart/form-data 방식에서는 99.999% 확률로 "파일"이 전송된다.
= 따라서 파일의 처리(저장)와 관련된 값들을 설정해야 요청을 수신할 수 있다.
= (1) 해석할 요청 객체 : request
= (2) 저장될 위치 : savePath
= (3) 허용할 업로드 제한크기(byte) : maxSize
= (4) 해석할 Encoding 방식 : encoding
= (5) [선택] 작명정책 객체 : policy
<%@page import="java.io.File"%>
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<h3>attach = <%=attach%></h3>
<%
String savePath = "c:/upload"; // 경로는 자유롭게 지정가능
int maxSize = 1 * 1024 * 1024;//1MB
String encoding = "UTF-8";
DefaultFileRenamePolicy policy = new DefaultFileRenamePolicy();
//요청 해석 및 파일 저장
MultipartRequest mRequest =
new MultipartRequest(request, savePath, maxSize, encoding, policy);
//데이터베이스에 저장하기 위하여 정보를 추출
String uploadName = mRequest.getOriginalFileName("attach");//원래이름
String saveName = mRequest.getFilesystemName("attach");//저장된이름
String contentType = mRequest.getContentType("attach");//파일의 MIME-TYPE
File target = mRequest.getFile("attach");//저장된 파일의 객체 반환(없으면 null)
long fileSize = target == null ? 0L : target.length();
%>
<h3>uploadName = <%=uploadName%></h3>
<h3>saveName = <%=saveName%></h3>
<h3>contentType = <%=contentType%></h3>
<h3>target = <%=target%></h3>
<h3>fileSize = <%=fileSize%></h3>
[ 파일 선택후 업로드 ]
[ 업로드 후 처리 페이지 ]
[ 저장 위치에 업로드 완료 ]
[ 게시판 - 파일 업로드 구현하기 ]
- SQL board_file 테이블 만들기
create table board_file(
board_file_no number primary key,
board_no references board(board_no) on delete cascade,
board_file_uploadname varchar2(256) not null,
board_file_savename varchar2(256) not null unique,
board_file_size number,
board_file_type varchar2(256)
);
create sequence board_file_seq;
- BoardFileDto 만들기
package home.beans;
public class BoardFileDto {
private int boardFileNo;
private int boardNo;
private String boardFileUploadname;
private String boardFileSavename;
private String boardFileType;
private long boardFileSize;
public BoardFileDto() {
super();
}
public int getBoardFileNo() {
return boardFileNo;
}
public void setBoardFileNo(int boardFileNo) {
this.boardFileNo = boardFileNo;
}
public int getBoardNo() {
return boardNo;
}
public void setBoardNo(int boardNo) {
this.boardNo = boardNo;
}
public String getBoardFileUploadname() {
return boardFileUploadname;
}
public void setBoardFileUploadname(String boardFileUploadname) {
this.boardFileUploadname = boardFileUploadname;
}
public String getBoardFileSavename() {
return boardFileSavename;
}
public void setBoardFileSavename(String boardFileSavename) {
this.boardFileSavename = boardFileSavename;
}
public String getBoardFileType() {
return boardFileType;
}
public void setBoardFileType(String boardFileType) {
this.boardFileType = boardFileType;
}
public long getBoardFileSize() {
return boardFileSize;
}
public void setBoardFileSize(long boardFileSize) {
this.boardFileSize = boardFileSize;
}
}
- BoardFileDao 파일 정보 저장 기능 만들기
package home.beans;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class BoardFileDao {
public void insert(BoardFileDto boardFileDto) throws Exception {
Connection con = JdbcUtils.connect2();
String sql = "insert into board_file values(board_file_seq.nextval, ?, ?, ?, ?, ?)";
PreparedStatement ps = con.prepareStatement(sql);
ps.setInt(1, boardFileDto.getBoardNo());
ps.setString(2, boardFileDto.getBoardFileUploadname());
ps.setString(3, boardFileDto.getBoardFileSavename());
ps.setLong(4, boardFileDto.getBoardFileSize());
ps.setString(5, boardFileDto.getBoardFileType());
ps.execute();
con.close();
}
}
- 게시글 등록 처리 (BoardWriteServlet.java) 수정 하기
[ 파일 업로드가 적용되기 전의 게시글 등록 서블릿 ]
package home.servlet.board;
import java.io.IOException;
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 home.beans.BoardDao;
import home.beans.BoardDto;
@WebServlet(urlPatterns = "/board/write.txt")
public class BoardWriteServlet extends HttpServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//입력 : BoardDto(boardTitle, boardContent)
//req.setCharacterEncoding("UTF-8");//EncodingFilter에서 처리
BoardDto boardDto = new BoardDto();
boardDto.setBoardTitle(req.getParameter("boardTitle"));
boardDto.setBoardContent(req.getParameter("boardContent"));
//아이디는 세션에서 수집하여 추가
boardDto.setBoardWriter((String)req.getSession().getAttribute("ses"));
//새글인지 답글인지 판정 : 파라미터에 boardSuperno가 있으면 답글이다
boolean answer = req.getParameter("boardSuperno") != null;
//답글일 경우에는 boardSuperno를 저장한다.
if(answer) {
boardDto.setBoardSuperno(Integer.parseInt(req.getParameter("boardSuperno")));
}
//처리
//(1) 일반적인 등록
//BoardDao boardDao = new BoardDao();
//boardDao.write(boardDto);
//(2) 번호를 알아내면서 등록
BoardDao boardDao = new BoardDao();
int boardNo = boardDao.getSequence();//시퀀스 번호 생성
boardDto.setBoardNo(boardNo);//게시글 데이터에 생성된 번호 추가
//답글일 경우 등록될 글의 정보를 상위글 정보를 기준으로 계산해야 한다.
if(answer) {
//1. 상위글의 모든 정보를 불러온다
BoardDto parentDto = boardDao.get(boardDto.getBoardSuperno());
//2. 상위글의 정보를 토대로 등록될 글의 정보를 계산한다
//= 그룹은 동일하게 유지하고 차수는 1 증가시켜서 설정한다
boardDto.setBoardGroupno(parentDto.getBoardGroupno());
boardDto.setBoardDepth(parentDto.getBoardDepth() + 1);
boardDao.writeAnswer(boardDto);//게시글 등록(답글)
}else{
boardDao.write2(boardDto);//게시글 등록(새글)
}
//출력
//(1) list.jsp로 리다이렉트
//resp.sendRedirect("list.jsp");
//(2) detail.jsp로 리다이렉트
resp.sendRedirect("detail.jsp?boardNo="+boardNo);
}
catch(Exception e) {
e.printStackTrace();
resp.sendError(500);
}
}
}
[ 파일 업로드를 적용한 서블릿 ]
= 사용자의 요청 방식이 multipart/form-data 방식으로 변경되었다.
= request를 기존의 형태로 수신할 수 없으며, MultipartRequest(cos.jar)를 이용하여 수신하도록 수정
= 저장위치는 C:/upload/board
= 용량제한은 10MB
= 인코딩은 UTF-8
= 기본 파일 이름 재정의 객체를 적용
= req.getParameter()는 mRequest.getParameter()로 바꿔서 사용
= 파일 관련된 명령만 따로 존재
= 파일업로드명 : mRequest.getOriginalFileName()
= 저장된 파일명 : mRequest.getFileSystemName();
= 파일 유형 : mRequest.getContentType()
= 파일 반환 : mRequest.getFile()
+ 파일이 없는 경우에 대한 조건 추가
package home.servlet.board;
import java.io.File;
import java.io.IOException;
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.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;
import home.beans.BoardDao;
import home.beans.BoardDto;
import home.beans.BoardFileDao;
import home.beans.BoardFileDto;
@WebServlet(urlPatterns = "/board/write.txt")
public class BoardWriteServlet extends HttpServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//multipart/form-data를 해석하기 위한 객체 생성
String savePath = "C:/upload/board";
int maxSize = 10 * 1024 * 1024;
String encoding = "UTF-8";
DefaultFileRenamePolicy policy = new DefaultFileRenamePolicy();
MultipartRequest mRequest =
new MultipartRequest(req, savePath, maxSize, encoding, policy);
//입력 : BoardDto(boardTitle, boardContent)
BoardDto boardDto = new BoardDto();
boardDto.setBoardTitle(mRequest.getParameter("boardTitle"));
boardDto.setBoardContent(mRequest.getParameter("boardContent"));
//아이디는 세션에서 수집하여 추가
boardDto.setBoardWriter((String)req.getSession().getAttribute("ses"));
//새글인지 답글인지 판정 : 파라미터에 boardSuperno가 있으면 답글이다
boolean answer = mRequest.getParameter("boardSuperno") != null;
//답글일 경우에는 boardSuperno를 저장한다.
if(answer) {
boardDto.setBoardSuperno(Integer.parseInt(mRequest.getParameter("boardSuperno")));
}
//(2) 번호를 알아내면서 등록
BoardDao boardDao = new BoardDao();
int boardNo = boardDao.getSequence();//시퀀스 번호 생성
boardDto.setBoardNo(boardNo);//게시글 데이터에 생성된 번호 추가
//답글일 경우 등록될 글의 정보를 상위글 정보를 기준으로 계산해야 한다.
if(answer) {
//1. 상위글의 모든 정보를 불러온다
BoardDto parentDto = boardDao.get(boardDto.getBoardSuperno());
//2. 상위글의 정보를 토대로 등록될 글의 정보를 계산한다
//= 그룹은 동일하게 유지하고 차수는 1 증가시켜서 설정한다
boardDto.setBoardGroupno(parentDto.getBoardGroupno());
boardDto.setBoardDepth(parentDto.getBoardDepth() + 1);
boardDao.writeAnswer(boardDto);//게시글 등록(답글)
}else{
boardDao.write2(boardDto);//게시글 등록(새글)
}
/**
* 게시글 등록을 모두 마친 뒤에 파일 정보를 데이터베이스에 저장하도록 설정
* 파일이 존재할 경우만 실행해야 한다.
*/
if(mRequest.getFile("attach") != null) {//파일이 attach란 이름으로 올라왔다면
BoardFileDto boardFileDto = new BoardFileDto();
boardFileDto.setBoardNo(boardNo);//게시글 번호
boardFileDto.setBoardFileSavename(mRequest.getFilesystemName("attach"));//실제저장된이름
boardFileDto.setBoardFileUploadname(mRequest.getOriginalFileName("attach"));//사용자가올린이름
boardFileDto.setBoardFileType(mRequest.getContentType("attach"));//파일 유형
File target = mRequest.getFile("attach");
boardFileDto.setBoardFileSize(target == null ? 0L : target.length());
BoardFileDao boardFileDao = new BoardFileDao();
boardFileDao.insert(boardFileDto);
}
//출력
//(2) detail.jsp로 리다이렉트
resp.sendRedirect("detail.jsp?boardNo="+boardNo);
}
catch(Exception e) {
e.printStackTrace();
resp.sendError(500);
}
}
}
- 게시글 등록 입력 (write.jsp) 수정 하기
[ 수정 전 코드 ]
<form action="write.txt" method="post">
[ 수정 후 코드]
<form action="write.txt" method="post" enctype="multipart/form-data">
[ 하단 에 추가 코드 ]
-> 첨부 파일 부분만 추가
<tbody>
<tr>
<th>제목</th>
<td><input type="text" name="boardTitle" required></td>
</tr>
<tr>
<th>내용</th>
<td>
<textarea name="boardContent" required rows="10" cols="60"></textarea>
</td>
</tr>
<!-- 첨부파일 -->
<tr>
<th>첨부</th>
<td>
<input type="file" name="attach">
</td>
</tr>
</tbody>
[ 게시글 파일 업로드 처리 구현 완료 ]
[ 회원 - 프로필 사진 구현하기 ]
- SQL member_profile 테이블 만들기
create table member_profile(
member_profile_no number primary key,
member_id references member(member_id) on delete cascade,
member_profile_uploadname varchar2(256) not null,
member_profile_savename varchar2(256) not null unique,
member_profile_size number,
member_profile_type varchar2(256)
);
create sequence member_profile_seq;
- MemberProfileDto 만들기
package home.beans;
public class MemberProfileDto {
private int memberProfileNo;
private String memberId;
private String memberProfileSavename;
private String memberProfileUploadname;
private String memberProfileType;
private long memberProfileSize;
public MemberProfileDto() {
super();
}
public int getMemberProfileNo() {
return memberProfileNo;
}
public void setMemberProfileNo(int memberProfileNo) {
this.memberProfileNo = memberProfileNo;
}
public String getMemberId() {
return memberId;
}
public void setMemberId(String memberId) {
this.memberId = memberId;
}
public String getMemberProfileSavename() {
return memberProfileSavename;
}
public void setMemberProfileSavename(String memberProfileSavename) {
this.memberProfileSavename = memberProfileSavename;
}
public String getMemberProfileUploadname() {
return memberProfileUploadname;
}
public void setMemberProfileUploadname(String memberProfileUploadname) {
this.memberProfileUploadname = memberProfileUploadname;
}
public String getMemberProfileType() {
return memberProfileType;
}
public void setMemberProfileType(String memberProfileType) {
this.memberProfileType = memberProfileType;
}
public long getMemberProfileSize() {
return memberProfileSize;
}
public void setMemberProfileSize(long memberProfileSize) {
this.memberProfileSize = memberProfileSize;
}
}
- MemberProfileDao 프로필 정보 등록 만들기
package home.beans;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class MemberProfileDao {
public void insert(MemberProfileDto memberProfileDto) throws Exception {
Connection con = JdbcUtils.connect2();
String sql = "insert into member_profile values(member_profile_seq.nextval, ?, ?, ?, ?, ?)";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, memberProfileDto.getMemberId());
ps.setString(2, memberProfileDto.getMemberProfileUploadname());
ps.setString(3, memberProfileDto.getMemberProfileSavename());
ps.setLong(4, memberProfileDto.getMemberProfileSize());
ps.setString(5, memberProfileDto.getMemberProfileType());
ps.execute();
con.close();
}
}
- 회원 가입 처리 (MemberJoinServlet.java) 수정 하기
[ 회원 가입 처리 서블릿 (기존 방식) ]
package home.servlet.member;
import java.io.IOException;
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 home.beans.MemberDao;
import home.beans.MemberDto;
//= 입력창의 전송형태에 따라 메소드를 선택할 수 있다.
//= service()는 모든 방식을 수용하는 메소드
//= doGet()은 GET 방식만 수용하는 메소드
//= doPost()는 POST 방식만 수용하는 메소드
@WebServlet(urlPatterns = "/member/join.txt")
public class MemberJoinServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//입력 : MemberDto
//= 문제점 : POST 방식으로 전송될 경우 유니코드가 ASCII코드로 변경되어 전송된다.
//= 해결책 : 수신한 데이터를 원래의 인코딩방식으로 변환하도록 지시한다.
//= 주의 : 반드시 수신 전에 복원명령을 작성해야 한다.
req.setCharacterEncoding("UTF-8");
MemberDto memberDto = new MemberDto();
memberDto.setMemberId(req.getParameter("memberId"));
memberDto.setMemberPw(req.getParameter("memberPw"));
memberDto.setMemberNick(req.getParameter("memberNick"));
memberDto.setMemberBirth(req.getParameter("memberBirth"));
memberDto.setMemberEmail(req.getParameter("memberEmail"));
memberDto.setMemberPhone(req.getParameter("memberPhone"));
//처리 : MemberDao
MemberDao memberDao = new MemberDao();
memberDao.join(memberDto);
//출력 : 리다이렉트
resp.sendRedirect("join_success.jsp");
}
catch(Exception e) {
e.printStackTrace();
resp.sendError(500);//사용자에게 500번 상태값을 전송(500은 Internal server error)
}
}
}
[ 수정 후 회원 가입 처리 서블릿 ]
package home.servlet.member;
import java.io.File;
import java.io.IOException;
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.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;
import home.beans.MemberDao;
import home.beans.MemberDto;
import home.beans.MemberProfileDao;
import home.beans.MemberProfileDto;
//= 입력창의 전송형태에 따라 메소드를 선택할 수 있다.
//= service()는 모든 방식을 수용하는 메소드
//= doGet()은 GET 방식만 수용하는 메소드
//= doPost()는 POST 방식만 수용하는 메소드
@WebServlet(urlPatterns = "/member/join.txt")
public class MemberJoinServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//MultiPart 요청 처리 준비
String savePath = "C:/upload";
int maxSize = 5 * 1024 * 1024;
String encoding = "UTF-8";
DefaultFileRenamePolicy policy = new DefaultFileRenamePolicy();
MultipartRequest mRequest =
new MultipartRequest(req, savePath, maxSize, encoding, policy);
MemberDto memberDto = new MemberDto();
memberDto.setMemberId(mRequest.getParameter("memberId"));
memberDto.setMemberPw(mRequest.getParameter("memberPw"));
memberDto.setMemberNick(mRequest.getParameter("memberNick"));
memberDto.setMemberBirth(mRequest.getParameter("memberBirth"));
memberDto.setMemberEmail(mRequest.getParameter("memberEmail"));
memberDto.setMemberPhone(mRequest.getParameter("memberPhone"));
//처리 : MemberDao
MemberDao memberDao = new MemberDao();
memberDao.join(memberDto);
//프로필이 있다면 등록 처리
if(mRequest.getFile("attach") != null) {//파일이 attach란 이름으로 올라왔다면
MemberProfileDto memberProfileDto = new MemberProfileDto();
memberProfileDto.setMemberId(memberDto.getMemberId());//회원 아이디
memberProfileDto.setMemberProfileSavename(mRequest.getFilesystemName("attach"));//실제저장된이름
memberProfileDto.setMemberProfileUploadname(mRequest.getOriginalFileName("attach"));//사용자가올린이름
memberProfileDto.setMemberProfileType(mRequest.getContentType("attach"));//파일 유형
memberProfileDto.setMemberProfileSize(mRequest.getFile("attach").length());
MemberProfileDao memberProfileDao = new MemberProfileDao();
memberProfileDao.insert(memberProfileDto);
}
//출력 : 리다이렉트
resp.sendRedirect("join_success.jsp");
}
catch(Exception e) {
e.printStackTrace();
resp.sendError(500);//사용자에게 500번 상태값을 전송(500은 Internal server error)
}
}
}
- 회원 가입 메인 페이지 (join.jsp) 수정 하기
[ 수정 전 코드 ]
<form action="join.txt" method="post">
[ 수정 후 코드]
<form action="join.txt" method="post" enctype="multipart/form-data">
[ 하단 에 추가 코드 ]
<tr>
<th>프로필</th>
<td>
<input type="file" name="attach" accept="image/*">
</td>
</tr>
[ 회원 프로필 사진 처리 구현 완료 ]
홈페이지 - 파일다운로드
[ 파일 다운로드 예제 ]
목표 : C:/upload(또는 다른 경로) 에 있는 test.txt라는 파일을 접속 시 바로 다운로드 하도록 페이지 구성
구조 : [test.txt] ---(입력)---> [서블릿] ---(출력)---> [사용자]
준비물 :
1. test.txt에 대한 파일 객체
2. test.txt에 대한 입력 스트림(FileInputStream)
3. 읽은 내용을 사용자에게 전달하기 위한 도구(resp)
package web09.servlet;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns = "/download.txt")
public class FileDownlodServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
File target = new File("c:/upload", "test.txt");
FileInputStream in = new FileInputStream(target);
byte[] buffer = new byte[1024]; //1024배수 기준
//[주의] 서버는 사용자에게 지금부터 보내는 내용이 "다운로드"를 위한 것임을 알려줘야 할 의무가 있다.
//= 추가적으로 "헤더" 설정을 해줘야 한다.
//= 헤더는 사용자가 받게 될 내용에 대한 정보
//= 보낼 내용의 유형, 크기, 이름, 방식, 설명, ...
//= resp.setHeader("이름", "값"); 형태로 설정한다.
//= header는 String밖에 설정할 수 없다.
resp.setHeader("Content-Type", "application/octet-stream");
//resp.setContentType("application/octet-stream");
resp.setHeader("Content-Disposition", "attachment; filename=test.txt");
resp.setHeader("Content-Encoding", "UTF-8");
resp.setHeader("Content-Length", String.valueOf(target.length()));
//resp.setContentLength((int)target.length());
while(true) {
int size = in.read(buffer);//size개 만큼 읽어오는 코드
if(size == -1) break;
resp.getOutputStream().write(buffer, 0, size);//size개만큼 내보내는 코드
}
in.close();
}
}
[ 게시판 - 파일 다운로드 구현하기 ]
- 게시판 파일 다운로드 처리 (BoardFileDownloadServlet.java) 만들기
package home.servlet.board;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
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 home.beans.BoardFileDao;
import home.beans.BoardFileDto;
@WebServlet(urlPatterns = "/board/file/download.txt")
public class BoardFileDownloadServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//입력 : 단일조회 항목(int boardFileNo)
//= 이 서블릿은 어떠한 경우에도 파일을 1개만 출력한다. 절대로 여러개를 동시에 출력할 수 없다.
int boardFileNo = Integer.parseInt(req.getParameter("boardFileNo"));
//처리
//1. board_file 단일조회
BoardFileDao boardFileDao = new BoardFileDao();
BoardFileDto boardFileDto = boardFileDao.get(boardFileNo);
//2. 파일 정보 설정
File dir = new File("C:/upload/board");
File target = new File(dir, boardFileDto.getBoardFileSavename());
InputStream in = new FileInputStream(target);
byte[] buffer = new byte[8192];
//3. 헤더 설정
//[주의] 파일명에는 띄어쓰기나 일부 특수문자, 한글 등의 유니코드가 포함될 수 있다.
//(1) 따옴표를 이용하여 띄어쓰기 등을 무시하도록 처리
//(2) 인코딩을 통해서 파일명에 존재하는 유니코드를 변환 처리(URLEncoder)
String uploadName = URLEncoder.encode(boardFileDto.getBoardFileUploadname(), "UTF-8");
uploadName = uploadName.replace("+", "%20");
resp.setHeader("Content-Type", "application/octet-stream");
resp.setHeader("Content-Disposition", "attachment; filename=\""+uploadName+"\"");
resp.setHeader("Content-Encoding", "UTF-8");
resp.setHeader("Content-Length", String.valueOf(boardFileDto.getBoardFileSize()));
//출력 : 파일 출력
//4. 데이터 출력(다운로드)
while(true) {
int size = in.read(buffer);
if(size == -1) break;
resp.getOutputStream().write(buffer, 0, size);
}
in.close();
}
catch(Exception e) {
e.printStackTrace();
resp.sendError(500);
}
}
}
- BoardFileDao 게시글에 해당하는 파일목록 조회 기능 만들기
public List<BoardFileDto> find(int boardNo) throws Exception {
Connection con = JdbcUtils.connect2();
String sql = "select * from board_file where board_no = ? order by board_file_no asc";
PreparedStatement ps = con.prepareStatement(sql);
ps.setInt(1, boardNo);
ResultSet rs = ps.executeQuery();
List<BoardFileDto> list = new ArrayList<>();
while(rs.next()) {
BoardFileDto boardFileDto = new BoardFileDto();
//copy
boardFileDto.setBoardFileNo(rs.getInt("board_file_no"));
boardFileDto.setBoardNo(rs.getInt("board_no"));
boardFileDto.setBoardFileSavename(rs.getString("board_file_savename"));
boardFileDto.setBoardFileUploadname(rs.getString("board_file_uploadname"));
boardFileDto.setBoardFileType(rs.getString("board_file_type"));
boardFileDto.setBoardFileSize(rs.getLong("board_file_size"));
list.add(boardFileDto);
}
con.close();
return list;
}
- 게시판 상세보기 (detail.jsp) 추가하기
[ 추가 전 코드 ]
boolean owner = boardDto.getBoardWriter().equals(memberId);
%>
<%
//현재 게시글에 대한 댓글을 조회
ReplyDao replyDao = new ReplyDao();
List<ReplyDto> replyList = replyDao.list(boardNo);
%>
<%-- 출력 --%>
<jsp:include page="/template/header.jsp"></jsp:include>
[ 추가 코드 ]
boolean owner = boardDto.getBoardWriter().equals(memberId);
%>
<%
//현재 게시글에 대한 댓글을 조회
ReplyDao replyDao = new ReplyDao();
List<ReplyDto> replyList = replyDao.list(boardNo);
%>
<%
//현재 게시글에 대한 파일정보를 조회
BoardFileDao boardFileDao = new BoardFileDao();
List<BoardFileDto> boardFileList = boardFileDao.find(boardNo);//파일이 여러 개일 경우
//BoardFileDto boardFileDto = boardFileDao.find2(boardNo);//파일이 한 개일 경우
%>
<%-- 출력 --%>
<jsp:include page="/template/header.jsp"></jsp:include>
[ 하단에 추가 코드 ]
<%-- 첨부파일이 있다면 첨부파일을 다운받을 수 있는 링크를 제공 --%>
<%if(!boardFileList.isEmpty()){ %>
<%for(BoardFileDto boardFileDto : boardFileList){ %>
<h6>
<%=boardFileDto.getBoardFileUploadname() %>
(<%=boardFileDto.getBoardFileSize()%> bytes)
<a href="file/download.txt?boardFileNo=<%=boardFileDto.getBoardFileNo()%>">
다운로드
</a>
</h6>
<%} %>
<%} %>
[ 게시판 파일 다운로드 구현 완료 ]
[ 마이페이지 기능 추가 하기 ]
- 프로필 이미지 추가되도록 설정
- 내가 작성한 게시글을 표시하도록 설정
[ 프로필 이미지 추가되도록 설정 ]
- MemberProfileDao 프로필 이미지 조회 기능 만들기 1
public MemberProfileDto get(int memberProfileNo) throws Exception {
Connection con = JdbcUtils.connect2();
String sql = "select * from member_profile where member_profile_no = ?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setInt(1, memberProfileNo);
ResultSet rs = ps.executeQuery();
MemberProfileDto memberProfileDto;
if(rs.next()) {
memberProfileDto = new MemberProfileDto();
memberProfileDto.setMemberProfileNo(rs.getInt("member_profile_no"));
memberProfileDto.setMemberId(rs.getString("member_id"));
memberProfileDto.setMemberProfileUploadname(rs.getString("member_profile_uploadname"));
memberProfileDto.setMemberProfileSavename(rs.getString("member_profile_savename"));
memberProfileDto.setMemberProfileSize(rs.getLong("member_profile_size"));
memberProfileDto.setMemberProfileType(rs.getString("member_profile_type"));
}
else {
memberProfileDto = null;
}
con.close();
return memberProfileDto;
}
- MemberProfileDao 프로필 이미지 조회 기능 만들기 2
public MemberProfileDto get(String memberId) throws Exception {
Connection con = JdbcUtils.connect2();
String sql = "select * from member_profile where member_id = ?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, memberId);
ResultSet rs = ps.executeQuery();
MemberProfileDto memberProfileDto;
if(rs.next()) {
memberProfileDto = new MemberProfileDto();
memberProfileDto.setMemberProfileNo(rs.getInt("member_profile_no"));
memberProfileDto.setMemberId(rs.getString("member_id"));
memberProfileDto.setMemberProfileUploadname(rs.getString("member_profile_uploadname"));
memberProfileDto.setMemberProfileSavename(rs.getString("member_profile_savename"));
memberProfileDto.setMemberProfileSize(rs.getLong("member_profile_size"));
memberProfileDto.setMemberProfileType(rs.getString("member_profile_type"));
}
else {
memberProfileDto = null;
}
con.close();
return memberProfileDto;
}
- 프로필 이미지 보기 처리 (MemberProfileServlet.java) 만들기
package home.servlet.member;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
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 home.beans.MemberProfileDao;
import home.beans.MemberProfileDto;
@WebServlet(urlPatterns = "/member/profile.txt")
public class MemberProfileServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//입력
int memberProfileNo = Integer.parseInt(req.getParameter("memberProfileNo"));
//처리
MemberProfileDao memberProfileDao = new MemberProfileDao();
MemberProfileDto memberProfileDto = memberProfileDao.get(memberProfileNo);
File dir = new File("C:/upload/member");
File target = new File(dir, memberProfileDto.getMemberProfileSavename());
InputStream in = new FileInputStream(target);
byte[] buffer = new byte[8192];
String encodeFilename = URLEncoder.encode(memberProfileDto.getMemberProfileUploadname(), "UTF-8");
encodeFilename = encodeFilename.replace("+", "%20");
resp.setHeader("Content-Type", "application/octet-stream");
resp.setHeader("Content-Disposition", "attachment; filename=\""+encodeFilename+"\"");
resp.setHeader("Content-Encoding", "UTF-8");
resp.setHeader("Content-Length", String.valueOf(memberProfileDto.getMemberProfileSize()));
while(true) {
int size = in.read(buffer);
if(size == -1) break;
resp.getOutputStream().write(buffer, 0, size);
}
in.close();
}
catch(Exception e) {
e.printStackTrace();
resp.sendError(500);
}
}
}
- 내 정보 보기 (mypage.jsp) 코드 추가
[ 상단에 코드 추가 ]
<%
//프로필 이미지 조회 : 아이디로 해도됨(1-1관계)
MemberProfileDao memberProfileDao = new MemberProfileDao();
MemberProfileDto memberProfileDto = memberProfileDao.get(memberId);
%>
[ 상단에 코드 추가 ]
<%if(memberProfileDto == null){ %>
<img src="https://via.placeholder.com?text=User" width="150" height="150">
<%}else{ %>
<img src="profile.txt?memberProfileNo=<%=memberProfileDto.getMemberProfileNo()%>" width="150" height="150">
<%} %>
[ 마이페이지 프로필 사진 구현 완료 ]
[ 내가 작성한 게시글을 표시하도록 설정 ]
- BoardDao 일치 검색 기능 만들기
public List<BoardDto> searchEquals(String column, String keyword) throws Exception {
Connection con = JdbcUtils.connect2();
String sql = "select * from board where #1 = ? order by board_no desc";
sql = sql.replace("#1", column);//정적 바인딩
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, keyword);
ResultSet rs = ps.executeQuery();
List<BoardDto> list = new ArrayList<>();
while(rs.next()) {
BoardDto boardDto = new BoardDto();
boardDto.setBoardNo(rs.getInt("board_no"));
boardDto.setBoardWriter(rs.getString("board_writer"));
boardDto.setBoardTitle(rs.getString("board_title"));
boardDto.setBoardContent(rs.getString("board_content"));
boardDto.setBoardTime(rs.getDate("board_time"));
boardDto.setBoardRead(rs.getInt("board_read"));
boardDto.setBoardReply(rs.getInt("board_reply"));
boardDto.setBoardSuperno(rs.getInt("board_superno"));
boardDto.setBoardGroupno(rs.getInt("board_groupno"));
boardDto.setBoardDepth(rs.getInt("board_depth"));
list.add(boardDto);
}
con.close();
return list;
}
}
- 내 정보 보기 (mypage.jsp) 코드 추가
[ 상단에 코드 추가 ]
<%
//내가 작성한 글 보여주기
BoardDao boardDao = new BoardDao();
List<BoardDto> myBoardList = boardDao.searchEquals("board_writer", memberId);
%>
[ 하단에 코드 추가 ]
<hr>
<h2>내가 작성한 게시글</h2>
<table border="1" width="90%">
<thead>
<tr>
<th>번호</th>
<th width="60%">제목</th>
<th>작성일</th>
<th>조회수</th>
</tr>
</thead>
<tbody align="center">
<%for(BoardDto boardDto : myBoardList){ %>
<tr>
<td><%=boardDto.getBoardNo()%></td>
<td align="left">
<%--
게시글의 제목을 출력하기 전에 차수에 따라 띄어쓰기를 진행한다
띄어쓰기는 HTML 특수문자인 을 사용한다.
답변글에는 reply icon을 추가로 출력한다.
--%>
<%
//if(boardDto.getBoardDepth() > 0){
if(boardDto.hasDepth()){
%>
<%for(int i=0; i < boardDto.getBoardDepth(); i++){ %>
<%} %>
<img src="<%=request.getContextPath()%>/resource/image/reply.png" width="15" height="15">
<%} %>
<a href="<%=request.getContextPath()%>/board/detail.jsp?boardNo=<%=boardDto.getBoardNo()%>">
<%=boardDto.getBoardTitle()%>
</a>
<!-- 제목 뒤에 댓글 개수를 출력한다 -->
<%
//if(boardDto.getBoardReply() > 0){
if(boardDto.isReplyExist()){
%>
[<%=boardDto.getBoardReply()%>]
<%} %>
</td>
<td><%=boardDto.getBoardTime()%></td>
<td><%=boardDto.getBoardRead()%></td>
</tr>
<%} %>
</tbody>
</table>
[ 마이페이지 내가 작성한 게시글 구현 완료 ]
[write.jsp] 전체 코드
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%-- 입력 : 답글일 경우에는 boardSuperno라는 값이 전달된다. --%>
<%
String boardSuperno = request.getParameter("boardSuperno");
%>
<%-- 처리 --%>
<%
boolean answer = boardSuperno != null;
String title = answer ? "답글 작성" : "새글 작성";
%>
<%-- 출력 --%>
<jsp:include page="/template/header.jsp"></jsp:include>
<h2><%=title%></h2>
<form action="write.txt" method="post" enctype="multipart/form-data">
<%-- 답글일 경우에는 반드시 "상위글번호(boardSuperno)" 를 처리페이지로 전송해야 한다 --%>
<%if(answer){ %>
<input type="hidden" name="boardSuperno" value="<%=boardSuperno%>">
<%} %>
<table border="0">
<tbody>
<tr>
<th>제목</th>
<td><input type="text" name="boardTitle" required></td>
</tr>
<tr>
<th>내용</th>
<td>
<textarea name="boardContent" required rows="10" cols="60"></textarea>
</td>
</tr>
<!-- 첨부파일 -->
<tr>
<th>첨부</th>
<td>
<input type="file" name="attach">
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2" align="right">
<input type="submit" value="등록">
</td>
</tr>
</tfoot>
</table>
</form>
<jsp:include page="/template/footer.jsp"></jsp:include>
[join.jsp] 전체 코드
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:include page="/template/header.jsp"></jsp:include>
<h1>회원가입</h1>
<form action="join.txt" method="post" enctype="multipart/form-data">
<table border="0">
<tbody>
<tr>
<th>아이디</th>
<td>
<input type="text" name="memberId" required>
</td>
</tr>
<tr>
<th>비밀번호</th>
<td>
<input type="password" name="memberPw" required>
</td>
</tr>
<tr>
<th>닉네임</th>
<td>
<input type="text" name="memberNick" required>
</td>
</tr>
<tr>
<th>생년월일</th>
<td>
<input type="date" name="memberBirth" required>
</td>
</tr>
<tr>
<th>이메일</th>
<td>
<input type="email" name="memberEmail">
</td>
</tr>
<tr>
<th>전화번호</th>
<td>
<input type="tel" name="memberPhone">
</td>
</tr>
<tr>
<tr>
<th>프로필</th>
<td>
<input type="file" name="attach" accept="image/*">
</td>
</tr>
<!--
colspan을 사용하면 셀 1개를 특정 칸 수만큼 늘릴 수 있다.
rowspan을 사용하면 셀 1개를 특정 줄 수만큼 늘릴 수 있다.
두 개를 동시에 사용하진 않는다
-->
<td colspan="2" align="right">
<input type="submit" value="가입">
</td>
</tr>
</tbody>
</table>
</form>
<jsp:include page="/template/footer.jsp"></jsp:include>
[mypage.jsp] 전체 코드
<%@page import="home.beans.MemberProfileDto"%>
<%@page import="home.beans.MemberProfileDao"%>
<%@page import="home.beans.BoardDto"%>
<%@page import="home.beans.BoardDao"%>
<%@page import="home.beans.TotalHistoryDto"%>
<%@page import="home.beans.TotalHistoryDao"%>
<%@page import="java.text.DecimalFormat"%>
<%@page import="java.text.Format"%>
<%@page import="home.beans.HistoryDto"%>
<%@page import="home.beans.HistoryDao"%>
<%@page import="java.util.List"%>
<%@page import="home.beans.MemberDto"%>
<%@page import="home.beans.MemberDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%-- 입력 : 현재 로그인한 회원ID - String memberId --%>
<%
String memberId = (String) session.getAttribute("ses");
%>
<%-- 처리 : 회원정보(MemberDto) --%>
<%
MemberDao memberDao = new MemberDao();
MemberDto memberDto = memberDao.get(memberId);
// 아래와 같이 조회하면 취소 여부를 알 수 없다.
// HistoryDao historyDao = new HistoryDao();
// List<HistoryDto> historyList = historyDao.findByMemberId(memberId);
// 새롭게 만든 뷰(total_history)를 이용하여 포인트 이력을 조회
TotalHistoryDao historyDao = new TotalHistoryDao();
List<TotalHistoryDto> historyList = historyDao.findByMemberId(memberId);
%>
<%
//내가 작성한 글 보여주기
BoardDao boardDao = new BoardDao();
List<BoardDto> myBoardList = boardDao.searchEquals("board_writer", memberId);
%>
<%
//프로필 이미지 조회 : 아이디로 해도됨(1-1관계)
MemberProfileDao memberProfileDao = new MemberProfileDao();
MemberProfileDto memberProfileDto = memberProfileDao.get(memberId);
%>
<%-- 출력 --%>
<jsp:include page="/template/header.jsp"></jsp:include>
<h2>회원 상세 정보</h2>
<%if(memberProfileDto == null){ %>
<img src="https://via.placeholder.com?text=User" width="150" height="150">
<%}else{ %>
<img src="profile.txt?memberProfileNo=<%=memberProfileDto.getMemberProfileNo()%>" width="150" height="150">
<%} %>
<table border="1" width="300">
<tbody>
<tr>
<th width="25%">아이디</th>
<td><%=memberDto.getMemberId()%></td>
</tr>
<tr>
<th>닉네임</th>
<td><%=memberDto.getMemberNick()%></td>
</tr>
<tr>
<th>생년월일</th>
<td><%=memberDto.getMemberBirthDay()%></td>
</tr>
<tr>
<th>이메일</th>
<td><%=memberDto.getMemberEmailString()%></td>
</tr>
<tr>
<th>전화번호</th>
<td><%=memberDto.getMemberPhoneString()%></td>
</tr>
<tr>
<th>가입일시</th>
<td><%=memberDto.getMemberJoin()%></td>
</tr>
<tr>
<th>포인트</th>
<td><%=memberDto.getMemberPoint()%></td>
</tr>
<tr>
<th>등급</th>
<td><%=memberDto.getMemberGrade()%></td>
</tr>
</tbody>
</table>
<h3><a href="password.jsp">비밀번호 변경</a></h3>
<h3><a href="edit.jsp">개인정보 변경</a></h3>
<h3><a href="check.jsp">회원 탈퇴</a></h3>
<hr>
<!-- 포인트 내역 출력 -->
<h2>포인트 상세 내역</h2>
<table border="1" width="500">
<thead>
<tr>
<th>일시</th>
<th>금액</th>
<th>메모</th>
<th>cancel</th>
<th>취소</th>
</tr>
</thead>
<tbody>
<%Format f = new DecimalFormat("#,##0"); %>
<%for(TotalHistoryDto historyDto : historyList) { %>
<tr>
<td align="center"><%=historyDto.getHistoryTime()%></td>
<td align="right"><%=f.format(historyDto.getHistoryAmount())%></td>
<td align="left"><%=historyDto.getHistoryMemo()%></td>
<td><%=historyDto.getCancel()%></td>
<td>
<%if(historyDto.available()){ %>
<%-- <a href="../point/cancel.txt?historyNo=<%=historyDto.getHistoryNo()%>">취소</a> 상대경로 --%>
<a href="<%=request.getContextPath()%>/point/cancel.txt?historyNo=<%=historyDto.getHistoryNo()%>">취소</a>
<%} %>
</td>
</tr>
<%} %>
</tbody>
</table>
<hr>
<h2>내가 작성한 게시글</h2>
<table border="1" width="90%">
<thead>
<tr>
<th>번호</th>
<th width="60%">제목</th>
<th>작성일</th>
<th>조회수</th>
</tr>
</thead>
<tbody align="center">
<%for(BoardDto boardDto : myBoardList){ %>
<tr>
<td><%=boardDto.getBoardNo()%></td>
<td align="left">
<%--
게시글의 제목을 출력하기 전에 차수에 따라 띄어쓰기를 진행한다
띄어쓰기는 HTML 특수문자인 을 사용한다.
답변글에는 reply icon을 추가로 출력한다.
--%>
<%
//if(boardDto.getBoardDepth() > 0){
if(boardDto.hasDepth()){
%>
<%for(int i=0; i < boardDto.getBoardDepth(); i++){ %>
<%} %>
<img src="<%=request.getContextPath()%>/resource/image/reply.png" width="15" height="15">
<%} %>
<a href="<%=request.getContextPath()%>/board/detail.jsp?boardNo=<%=boardDto.getBoardNo()%>">
<%=boardDto.getBoardTitle()%>
</a>
<!-- 제목 뒤에 댓글 개수를 출력한다 -->
<%
//if(boardDto.getBoardReply() > 0){
if(boardDto.isReplyExist()){
%>
[<%=boardDto.getBoardReply()%>]
<%} %>
</td>
<td><%=boardDto.getBoardTime()%></td>
<td><%=boardDto.getBoardRead()%></td>
</tr>
<%} %>
</tbody>
</table>
<jsp:include page="/template/footer.jsp"></jsp:include>
[detail.jsp] 전체 코드
<%@page import="home.beans.BoardFileDto"%>
<%@page import="home.beans.BoardFileDao"%>
<%@page import="home.beans.ReplyDto"%>
<%@page import="java.util.List"%>
<%@page import="home.beans.ReplyDao"%>
<%@page import="java.util.HashSet"%>
<%@page import="java.util.Set"%>
<%@page import="home.beans.BoardDto"%>
<%@page import="home.beans.BoardDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%-- 번외 : 수정 버튼을 눌렀을 때 처리되도록 구현하는 스크립트(나중에 배움) --%>
<script src="https://code.jquery.com/jquery-latest.js"></script>
<script>
$(function(){
$(".view-row").find(".edit-btn").click(function(){
$(this).parents("tr.view-row").hide();
$(this).parents("tr.view-row").next("tr.edit-row").show();
});
$(".edit-row").find(".edit-cancel-btn").click(function(){
$(this).parents("tr.edit-row").hide();
$(this).parents("tr.edit-row").prev("tr.view-row").show();
});
$(".edit-row").hide();
});
</script>
<%-- 입력 : 게시글번호(boardNo) --%>
<%
int boardNo = Integer.parseInt(request.getParameter("boardNo"));
%>
<%-- 처리 --%>
<%
String memberId = (String)session.getAttribute("ses");
BoardDao boardDao = new BoardDao();
//1. boardViewedNo 라는 이름의 저장소를 세션에서 꺼내어 본다.
Set<Integer> boardViewedNo = (Set<Integer>)session.getAttribute("boardViewedNo");
//2. boardViewedNo 가 null 이면 "처음 글을 읽는 상태"임을 말하므로 저장소를 신규로 생성
if(boardViewedNo == null){
boardViewedNo = new HashSet<>();
//System.out.println("처음으로 글을 읽기 시작했습니다(저장소 생성)");
}
//3. 현재 글 번호를 저장소에 추가해본다
//3-1. 추가가 된다면 이 글은 처음 읽는 글
//3-2. 추가가 안된다면 이 글은 두 번 이상 읽은 글
if (boardViewedNo.add(boardNo)) {//처음 읽은 글인 경우
boardDao.readUp(boardNo, memberId);//조회수 증가(남에 글일때만)
//System.out.println("이 글은 처음 읽는 글입니다");
} else {
//System.out.println("이 글은 읽은 적이 있습니다");
}
//System.out.println("저장소 : " + boardViewedNo);
//4. 저장소 갱신
session.setAttribute("boardViewedNo", boardViewedNo);
BoardDto boardDto = boardDao.get(boardNo);//단일조회
//본인 글인지 아닌지를 판정하는 변수
//boolean owner = 세션의ses 값과 게시글 작성자가 같은가?;
boolean owner = boardDto.getBoardWriter().equals(memberId);
%>
<%
//현재 게시글에 대한 댓글을 조회
ReplyDao replyDao = new ReplyDao();
List<ReplyDto> replyList = replyDao.list(boardNo);
%>
<%
//현재 게시글에 대한 파일정보를 조회
BoardFileDao boardFileDao = new BoardFileDao();
List<BoardFileDto> boardFileList = boardFileDao.find(boardNo);//파일이 여러 개일 경우
//BoardFileDto boardFileDto = boardFileDao.find2(boardNo);//파일이 한 개일 경우
%>
<%-- 출력 --%>
<jsp:include page="/template/header.jsp"></jsp:include>
<h2><%=boardDto.getBoardNo()%>번 게시글</h2>
<table border="1" width="80%">
<tbody>
<tr>
<td>
<h3><%=boardDto.getBoardTitle()%></h3>
</td>
</tr>
<tr>
<td>
등록일 : <%=boardDto.getBoardTime()%>
|
작성자 : <%=boardDto.getBoardWriter()%>
|
조회수 : <%=boardDto.getBoardRead()%>
</td>
</tr>
<!-- 답답해 보이지 않도록 기본높이를 부여 -->
<tr height="250" valign="top">
<td>
<pre><%=boardDto.getBoardContent()%></pre>
</td>
</tr>
<tr>
<td align="right">
<a href="write.jsp">글쓰기</a>
<a href="write.jsp?boardSuperno=<%=boardDto.getBoardNo()%>">답글쓰기</a>
<a href="list.jsp">목록보기</a>
<%if(owner){ %>
<a href="edit.jsp?boardNo=<%=boardDto.getBoardNo()%>">수정하기</a>
<%-- <a href="delete.txt?boardNo=<%=boardNo%>">삭제하기</a> --%>
<a href="delete.txt?boardNo=<%=boardDto.getBoardNo()%>">삭제하기</a>
<%} %>
</td>
</tr>
</tbody>
</table>
<%-- 댓글 작성, 목록 영역 --%>
<form action="./reply/insert.txt" method="post">
<input type="hidden" name="boardNo" value="<%=boardDto.getBoardNo()%>">
<table border="0" width="80%">
<tbody>
<tr>
<td>
<textarea name="replyContent" required rows="4" cols="80"></textarea>
</td>
<td>
<input type="submit" value="댓글작성">
</td>
</tr>
</tbody>
</table>
</form>
<%if(replyList.isEmpty()){ %>
<!-- 댓글이 없을 경우에 표시할 테이블 -->
<table border="1" width="80%">
<tbody>
<tr><th>작성된 댓글이 없습니다</th></tr>
</tbody>
</table>
<%}else{ %>
<!-- 댓글이 있을 경우에 표시할 테이블 -->
<table border="1" width="80%">
<tbody>
<%for(ReplyDto replyDto : replyList){ %>
<%
//본인 댓글인지 판정 : 세션의 회원아이디와 댓글의 작성자를 비교
//작성자 댓글인지 판정 : 게시글 작성자와 댓글의 작성자를 비교
boolean myReply = memberId.equals(replyDto.getReplyWriter());
boolean ownerReply = boardDto.getBoardWriter().equals(replyDto.getReplyWriter());
%>
<tr class="view-row">
<td width="30%">
<%=replyDto.getReplyWriter()%>
<%-- 게시글 작성자의 댓글에는 표시 --%>
<%if(ownerReply){ %>
(작성자)
<%} %>
<br>
(<%=replyDto.getReplyFullTime()%>)
</td>
<td>
<pre><%=replyDto.getReplyContent()%></pre>
</td>
<td width="15%">
<%-- 현재 사용자가 작성한 글에만 수정, 삭제를 표시 --%>
<%if(myReply){ %>
<a class="edit-btn">수정</a> |
<a href="reply/delete.txt?boardNo=<%=replyDto.getBoardNo()%>&replyNo=<%=replyDto.getReplyNo()%>">삭제</a>
<%} %>
</td>
</tr>
<%-- 본인 글일 경우 수정을 위한 공간을 추가적으로 생성 --%>
<%if(myReply){ %>
<tr class="edit-row">
<td colspan="3">
<form action="reply/edit.txt" method="post">
<input type="hidden" name="replyNo" value="<%=replyDto.getReplyNo()%>">
<input type="hidden" name="boardNo" value="<%=replyDto.getBoardNo()%>">
<textarea name="replyContent" required rows="4" cols="80"><%=replyDto.getReplyContent()%></textarea>
<input type="submit" value="수정">
<a class="edit-cancel-btn">취소</a>
</form>
</td>
</tr>
<%} %>
<%} %>
</tbody>
</table>
<%} %>
<%-- 첨부파일이 있다면 첨부파일을 다운받을 수 있는 링크를 제공 --%>
<%if(!boardFileList.isEmpty()){ %>
<%for(BoardFileDto boardFileDto : boardFileList){ %>
<h6>
<%=boardFileDto.getBoardFileUploadname() %>
(<%=boardFileDto.getBoardFileSize()%> bytes)
<a href="file/download.txt?boardFileNo=<%=boardFileDto.getBoardFileNo()%>">
다운로드
</a>
<%-- <img src="file/download.txt?boardFileNo=<%=boardFileDto.getBoardFileNo()%>" width="50" height="50"> --%>
</h6>
<%} %>
<%} %>
<jsp:include page="/template/footer.jsp"></jsp:include>
'Java 웹 개발' 카테고리의 다른 글
21.11.03 - 웹 개발 입문 58일차 (0) | 2021.11.03 |
---|---|
21.11.02 - 웹 개발 입문 57일차 (0) | 2021.11.02 |
21.10.28 - 웹 개발 입문 54일차 (0) | 2021.10.28 |
21.10.27 - 웹 개발 입문 53일차 (0) | 2021.10.27 |
21.10.26 - 웹 개발 입문 52일차 (0) | 2021.10.26 |