파일 첨부 예제
Oracle SQL Developer를 이용해 아래 코드를 실행 시킨다.
/* 첨부파일 테이블용 시퀀스 생성 */
CREATE SEQUENCE ATCH_FILE_SEQ;
/* 첨부파일 관련 DDL */
CREATE TABLE ATCH_FILE
( ATCH_FILE_ID NUMBER NOT NULL ENABLE,
CREAT_DT DATE DEFAULT SYSDATE NOT NULL ENABLE,
USE_AT CHAR(1 BYTE) DEFAULT 'Y',
CONSTRAINT ATCH_FILE_PK PRIMARY KEY (ATCH_FILE_ID)
);
COMMENT ON COLUMN ATCH_FILE.ATCH_FILE_ID IS '첨부파일ID';
COMMENT ON COLUMN ATCH_FILE.CREAT_DT IS '생성일시';
COMMENT ON COLUMN ATCH_FILE.USE_AT IS '사용여부';
CREATE TABLE ATCH_FILE_DETAIL
( ATCH_FILE_ID NUMBER NOT NULL ENABLE,
FILE_SN NUMBER(3) NOT NULL ENABLE,
FILE_STRE_COURS VARCHAR2(2000 BYTE) NOT NULL ENABLE,
STRE_FILE_NM VARCHAR2(255 BYTE) NOT NULL ENABLE,
ORIGNL_FILE_NM VARCHAR2(255 BYTE),
FILE_EXTSN VARCHAR2(20 BYTE) NOT NULL ENABLE,
FILE_CN CLOB,
FILE_SIZE NUMBER(8,0),
CONSTRAINT ATCH_FILE_DETAIL_PK PRIMARY KEY (ATCH_FILE_ID, FILE_SN)
);
COMMENT ON COLUMN ATCH_FILE_DETAIL.ATCH_FILE_ID IS '첨부파일ID';
COMMENT ON COLUMN ATCH_FILE_DETAIL.FILE_SN IS '파일순번';
COMMENT ON COLUMN ATCH_FILE_DETAIL.FILE_STRE_COURS IS '파일저장경로';
COMMENT ON COLUMN ATCH_FILE_DETAIL.STRE_FILE_NM IS '저장파일명';
COMMENT ON COLUMN ATCH_FILE_DETAIL.ORIGNL_FILE_NM IS '원본파일명';
COMMENT ON COLUMN ATCH_FILE_DETAIL.FILE_EXTSN IS '파일확장자';
COMMENT ON COLUMN ATCH_FILE_DETAIL.FILE_CN IS '파일내용';
COMMENT ON COLUMN ATCH_FILE_DETAIL.FILE_SIZE IS '파일크기';


atchFile.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="atchFile">
<insert id="insertAtchFile" parameterType="kr.or.ddit.common.vo.AtchFileVO">
<!--
atchFileId를 따로 담아놓기 위해 selectKey를 사용 / BEFORE로 인해 insert 하기 전에 작동
parameterType의 VO인 atchFileId에 값이 들어감
-->
<selectKey keyProperty="atchFileId" resultType="long" order="BEFORE">
select ATCH_FILE_SEQ.nextval from dual
</selectKey>
insert into atch_file
(ATCH_FILE_ID,
CREAT_DT,
USE_AT)
values
(
#{atchFileId},
sysdate,
'Y'
)
</insert>
<insert id="insertAtchFileDetail">
insert into atch_file_detail
(ATCH_FILE_ID,
FILE_SN,
FILE_STRE_COURS,
STRE_FILE_NM,
ORIGNL_FILE_NM,
FILE_EXTSN,
FILE_CN,
FILE_SIZE)
values
(
#{atchFileId},
(select nvl(max(file_sn),0)+1
from atch_file_detail
where atch_file_id = #{atchFileId}),
#{fileStreCours},
#{streFileNm},
#{orignlFileNm},
#{fileExtsn},
#{fileCn},
#{fileSize}
)
</insert>
<resultMap type="kr.or.ddit.common.vo.AtchFileVO" id="atchFileMap">
<result property="atchFileId" column="ATCH_FILE_ID" />
<result property="fileSn" column="FILE_SN" />
<result property="fileStreCours" column="FILE_STRE_COURS" />
<result property="streFileNm" column="STRE_FILE_NM" />
<result property="orignlFileNm" column="ORIGNL_FILE_NM" />
<result property="fileExtsn" column="FILE_EXTSN" />
<result property="fileCn" column="FILE_CN" />
<result property="fileSize" column="FILE_SIZE" />
</resultMap>
<!--
목록을 가져올지, 디테일한 내용을 가져올지 선택하기 위해서 2가지로 나눔
select의 경우 resultType 또는 resultMap으로 설정 필수
-->
<select id="getAtchFileList" resultMap="atchFileMap">
select * from atch_file a, atch_file_detail b
where a.atch_file_id = b.atch_file_id
and b.atch_file_id = #{atchFileId}
</select>
<select id="getAtchFileDetail" resultMap="atchFileMap">
select * from atch_file a, atch_file_detail b
where a.atch_file_id = b.atch_file_id
and b.atch_file_id = #{atchFileId}
and b.file_sn = #{fileSn}
</select>
</mapper>
AtchFileVO.java
package kr.or.ddit.common.vo;
import java.time.LocalDate;
public class AtchFileVO {
private long atchFileId = -1; // 첨부파일ID
private LocalDate creatDt; // 생성일자
private String useAt; // 사용여부
private int fileSn = 1; // 파일 순번
private String fileStreCours; // 파일 저장 경로
private String streFileNm; // 저장 파일명
private String orignlFileNm; // 원본 파일명
private String fileExtsn; // 파일 확장자
private String fileCn; // 파일 내용(비고란)
private long fileSize = 0; // 파일 사이즈
public long getAtchFileId() {
return atchFileId;
}
public void setAtchFileId(long atchFileId) {
this.atchFileId = atchFileId;
}
public LocalDate getCreatDt() {
return creatDt;
}
public void setCreatDt(LocalDate creatDt) {
this.creatDt = creatDt;
}
public String getUseAt() {
return useAt;
}
public void setUseAt(String useAt) {
this.useAt = useAt;
}
public int getFileSn() {
return fileSn;
}
public void setFileSn(int fileSn) {
this.fileSn = fileSn;
}
public String getFileStreCours() {
return fileStreCours;
}
public void setFileStreCours(String fileStreCours) {
this.fileStreCours = fileStreCours;
}
public String getStreFileNm() {
return streFileNm;
}
public void setStreFileNm(String streFileNm) {
this.streFileNm = streFileNm;
}
public String getOrignlFileNm() {
return orignlFileNm;
}
public void setOrignlFileNm(String orignlFileNm) {
this.orignlFileNm = orignlFileNm;
}
public String getFileExtsn() {
return fileExtsn;
}
public void setFileExtsn(String fileExtsn) {
this.fileExtsn = fileExtsn;
}
public String getFileCn() {
return fileCn;
}
public void setFileCn(String fileCn) {
this.fileCn = fileCn;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
@Override
public String toString() {
return "AtchFileVO [atchFileId=" + atchFileId + ", creatDt=" + creatDt + ", useAt=" + useAt + ", fileSn="
+ fileSn + ", fileStreCours=" + fileStreCours + ", streFileNm=" + streFileNm + ", orignlFileNm="
+ orignlFileNm + ", fileExtsn=" + fileExtsn + ", fileCn=" + fileCn + ", fileSize=" + fileSize + "]";
}
}
IAtchFileDao.java
package kr.or.ddit.common.dao;
import java.util.List;
import kr.or.ddit.common.vo.AtchFileVO;
public interface IAtchFileDao {
/**
* 첨부파일 저장
*
* @param atchFileVO
* @return
*/
public int insertAtchFile(AtchFileVO atchFileVO);
/**
* 세부 첨부파일 정보 저장
*
* @param atchFileVO
* @return
*/
public int insertAtchFileDetail(AtchFileVO atchFileVO);
/**
* 첨부파일 목록 조회하기
*
* @param atchFileVO
* @return
*/
public List<AtchFileVO> getAtchFileList(AtchFileVO atchFileVO);
/**
* 첨부파일 세부정보 조회하기
*
* @param atchFileVO
* @return
*/
public AtchFileVO getAtchFileDetail(AtchFileVO atchFileVO);
}
AtchFileDaoImpl.java
package kr.or.ddit.common.dao;
import java.util.ArrayList;
import java.util.List;
import org.apache.ibatis.exceptions.PersistenceException;
import org.apache.ibatis.session.SqlSession;
import kr.or.ddit.common.vo.AtchFileVO;
import kr.or.ddit.util.MyBatisUtil;
public class AtchFileDaoImpl implements IAtchFileDao{
private static IAtchFileDao fileDao;
public AtchFileDaoImpl() {
}
public static IAtchFileDao getInstance() {
if(fileDao == null) {
fileDao = new AtchFileDaoImpl();
}
return fileDao;
}
@Override
public int insertAtchFile(AtchFileVO atchFileVO) {
SqlSession session = MyBatisUtil.getSqlSession();
int cnt = 0;
try {
cnt = session.insert("atchFile.insertAtchFile", atchFileVO);
if(cnt > 0) {
session.commit();
}
} catch (PersistenceException ex) {
session.rollback();
ex.printStackTrace();
} finally {
session.close();
}
return cnt;
}
@Override
public int insertAtchFileDetail(AtchFileVO atchFileVO) {
SqlSession session = MyBatisUtil.getSqlSession();
int cnt = 0;
try {
cnt = session.insert("atchFile.insertAtchFileDetail", atchFileVO);
if(cnt > 0) {
session.commit();
}
} catch (PersistenceException ex) {
session.rollback();
ex.printStackTrace();
} finally {
session.close();
}
return cnt;
}
@Override
public List<AtchFileVO> getAtchFileList(AtchFileVO atchFileVO) {
SqlSession session = MyBatisUtil.getSqlSession();
List<AtchFileVO> atchFileList = new ArrayList<AtchFileVO>();
try {
atchFileList = session.selectList("atchFile.getAtchFileList", atchFileVO);
} catch (PersistenceException ex) {
session.rollback();
ex.printStackTrace();
} finally {
session.close();
}
return atchFileList;
}
@Override
public AtchFileVO getAtchFileDetail(AtchFileVO atchFileVO) {
AtchFileVO fileVO = null;
SqlSession session = MyBatisUtil.getSqlSession(true);
try {
fileVO = session.selectOne("atchFile.getAtchFileDetail", atchFileVO);
} catch (PersistenceException ex) {
ex.printStackTrace();
} finally {
session.close();
}
return fileVO;
}
public static void main(String[] args) {
IAtchFileDao fileDao = AtchFileDaoImpl.getInstance();
AtchFileVO atchFileVO = new AtchFileVO();
int cnt = fileDao.insertAtchFile(atchFileVO);
if(cnt > 0) {
System.out.println("등록 성공");
System.out.println("atchFileId => " + atchFileVO.getAtchFileId());
atchFileVO.setFileStreCours("d:/D_Other/answktkwls");
atchFileVO.setStreFileNm("answktkwls");
atchFileVO.setOrignlFileNm("hello.jpg");
atchFileVO.setFileExtsn("jpg");
atchFileVO.setFileCn("");
atchFileVO.setFileSize(100000);
int cnt2 = fileDao.insertAtchFileDetail(atchFileVO);
if(cnt2 > 0) {
System.out.println("파일 상세테이블 등록 성공...");
} else {
System.out.println("파일 상세테이블 등록 실패...");
}
List<AtchFileVO> atchFileList = fileDao.getAtchFileList(atchFileVO);
System.out.println("atchFileList size : " + atchFileList.size());
atchFileVO = fileDao.getAtchFileDetail(atchFileVO);
System.out.println("조회된 첨부파일 상세정보 => " + atchFileVO);
} else {
System.out.println("등록 실패");
}
}
}
IAtchFileService.java
package kr.or.ddit.common.service;
import java.util.Collection;
import java.util.List;
import javax.servlet.http.Part;
import kr.or.ddit.common.vo.AtchFileVO;
public interface IAtchFileService {
/**
* 첨부파일 저장
*
* @param atchFileVO
* @return
*/
public AtchFileVO saveAtchFileList(Collection<Part> parts) throws Exception;
/**
* 첨부파일 목록 조회하기
*
* @param atchFileVO
* @return
*/
public List<AtchFileVO> getAtchFileList(AtchFileVO atchFileVO);
/**
* 첨부파일 세부정보 조회하기
*
* @param atchFileVO
* @return
*/
public AtchFileVO getAtchFileDetail(AtchFileVO atchFileVO);
}
AtchFileServiceImpl.java
package kr.or.ddit.common.service;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.Part;
import kr.or.ddit.common.dao.AtchFileDaoImpl;
import kr.or.ddit.common.dao.IAtchFileDao;
import kr.or.ddit.common.vo.AtchFileVO;
/**
* 공통 첨부파일을 처리하기 위한 서비스 클래스
* @author PC-10
*
*/
public class AtchFileServiceImpl implements IAtchFileService{
private static IAtchFileService fileService;
private IAtchFileDao fileDao;
private AtchFileServiceImpl() {
fileDao = AtchFileDaoImpl.getInstance();
}
public static IAtchFileService getInstance() {
if(fileService == null) {
fileService = new AtchFileServiceImpl();
}
return fileService;
}
@Override
public AtchFileVO saveAtchFileList(Collection<Part> parts) throws Exception {
String uploadPath = "d:/D_Other/upload_files";
File uploadDir = new File(uploadPath);
if(!uploadDir.exists()) {
uploadDir.mkdir();
}
AtchFileVO atchFileVO = null;
boolean isFirstFile = true; // 첫번째 파일인지 여부 체크
for (Part part : parts) {
System.out.println("Content-Disposition => "
+ part.getHeader("Content-Disposition"));
String fileName = part.getSubmittedFileName(); // 전송된 파일명
if(fileName != null && !fileName.equals("")) {
// 폼필드가 아니거나 파일명이 존재하는 경우... (첨부파일이 존재하는 경우...)
if(isFirstFile) { // 첫번째 첨부파일인 경우...
isFirstFile = false;
// 기본 첨부파일 정보 저장
atchFileVO = new AtchFileVO();
fileDao.insertAtchFile(atchFileVO);
}
//////////////////////////////////////////////////
String orignFileName = fileName; // 원본 파일명
long fileSize = part.getSize(); // 파일 크기
String saveFileName = ""; // 저장파일명
String saveFilePath = ""; // 저장파일경로
saveFileName = UUID.randomUUID().toString().replace("-", ""); // 값이 랜덤하게 추출됨
saveFilePath = uploadPath + "/" + saveFileName;
// 확장자 추출하기
String fileExtension = orignFileName.lastIndexOf(".") < 0 ? ""
: orignFileName.substring(orignFileName.lastIndexOf(".") + 1);
part.write(saveFilePath); // 파일 저장
atchFileVO.setFileStreCours(saveFilePath);
atchFileVO.setStreFileNm(saveFileName);
atchFileVO.setOrignlFileNm(orignFileName);
atchFileVO.setFileExtsn(fileExtension);
atchFileVO.setFileSize(fileSize);
atchFileVO.setFileCn("");
// 첨부파일 세부정보 저장
fileDao.insertAtchFileDetail(atchFileVO);
part.delete(); // 임시 업로드 파일 삭제하기
}
}
return atchFileVO;
}
@Override
public List<AtchFileVO> getAtchFileList(AtchFileVO atchFileVO) {
return fileDao.getAtchFileList(atchFileVO);
}
@Override
public AtchFileVO getAtchFileDetail(AtchFileVO atchFileVO) {
return fileDao.getAtchFileDetail(atchFileVO);
}
public static void main(String[] args) {
System.out.println(UUID.randomUUID().toString().replace("-", ""));
}
}
- 파일 첨부 추가
파일 첨부 추가를 위해 MYMEMBER테이블을 이용한다.
MemberVO.java
package kr.or.ddit.member.vo;
import java.time.LocalDate;
/**
* DB 테이블에 있는 컬럼명을 기준으로 데이터를 객체화 하기 위한 클래스
* <p>
* DB테이블의 컬럼과 클래스의 멤버변수를 매핑하는 역할을 수행한다.
* </p>
* @author PC-10
*
*/
public class MemberVO {
private String memId;
private String memName;
private String memTel;
private String memAddr;
private LocalDate regDt;
private long atchFileId = -1;
public MemberVO(String memId, String memName, String memTel, String memAddr) {
this.memId = memId;
this.memName = memName;
this.memTel = memTel;
this.memAddr = memAddr;
}
public MemberVO() {
}
public long getAtchFileId() {
return atchFileId;
}
public void setAtchFileId(long atchFileId) {
this.atchFileId = atchFileId;
}
public String getMemId() {
return memId;
}
public void setMemId(String memId) {
this.memId = memId;
}
public String getMemName() {
return memName;
}
public void setMemName(String memName) {
this.memName = memName;
}
public String getMemTel() {
return memTel;
}
public void setMemTel(String memTel) {
this.memTel = memTel;
}
public String getMemAddr() {
return memAddr;
}
public void setMemAddr(String memAddr) {
this.memAddr = memAddr;
}
public LocalDate getRegDt() {
return regDt;
}
public void setRegDt(LocalDate regDt) {
this.regDt = regDt;
}
@Override
public String toString() {
return "MemberVO [memId=" + memId + ", memName=" + memName + ", memTel=" + memTel + ", memAddr=" + memAddr
+ "]";
}
}
member.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="member">
<!--
이 영역에 sql문에 맞는 태그를 사용하여 SQL문을 기술한다.
사용할 수 있는 기본적인 태그들
<select> ~~~ </select>
<insert> ~~~ </insert>
<update> ~~~ </update>
<delete> ~~~ </delete>
위 태그에서 사용되는 주요 속성들
1) id : 해당 태그를 호출할 때 namespace값과 연결하여 사용하는 id값
2) parameterType : 파라미터 객체의 타입정보를 지정한다.
(보통 VO클래스명, 자바의 데이터타입 등이 사용된다. ALias명 사용 가능함.)
3) resultType : select문을 실행한 결과값을 담을 객체타입을 지정한다.
(보통 VO클래스명, 자바의 데이터타입 등이 사용된다. ALias명 사용 가능함.)
4) resultMap : 결과 레코드 컬럼명과 VO객체의 속성명이 다를 경우에 적절한 매핑을 위해 사용한다.
-->
<insert id="insertMember" parameterType="kr.or.ddit.member.vo.MemberVO">
insert into mymember
(mem_id, mem_name, mem_tel, mem_addr, atch_file_id)
values (#{memId}, #{memName}, #{memTel}, #{memAddr}, #{atchFileId})
</insert>
<update id="updateMember" parameterType="kr.or.ddit.member.vo.MemberVO">
update mymember
set mem_name = #{memName},
mem_tel = #{memTel},
mem_addr = #{memAddr},
atch_file_id = #{atchFileId}
where mem_id = #{memId}
</update>
<delete id="deleteMember" parameterType="String">
delete from mymember where mem_id = #{오병준}
</delete>
<select id="selectAllMember" resultType="kr.or.ddit.member.vo.MemberVO">
select mem_id as memId,
mem_name as memName,
mem_tel as memTel,
mem_addr as memAddr,
reg_dt as regDt,
atch_file_id as atchFileId
from mymember
</select>
<select id="getMember" resultType="kr.or.ddit.member.vo.MemberVO">
select mem_id as memId,
mem_name as memName,
mem_tel as memTel,
mem_addr as memAddr,
atch_file_id as atchFileId
from mymember
where mem_id = #{memId}
</select>
<select id="checkMember" resultType="int">
select count(*) as cnt
from mymember
where mem_id = #{memId}
</select>
<resultMap type="kr.or.ddit.member.vo.MemberVO" id="memMap">
<result column="mem_id" property="memId"/>
<result column="mem_name" property="memName"/>
<result column="mem_tel" property="memTel"/>
<result column="mem_addr" property="memAddr"/>
<result column="reg_dt" property="regDt"/>
<result column="atch_file_id" property="atchFileId"/>
</resultMap>
<select id="searchMember" resultMap="memMap">
select * from mymember where 1=1
<if test='memId != null and memId != ""'>
and mem_id = #{memId}
</if>
<if test='memName != null and !memName.equals("")'>
and mem_name = #{memName}
</if>
<if test='memTel != null and !memTel.equals("")'>
and mem_tel = #{memTel}
</if>
<if test='memAddr != null and !memAddr.equals("")'>
and mem_addr like '%' || #{memAddr} || '%'
</if>
</select>
</mapper>
list.jsp
<%@page import="kr.or.ddit.member.vo.MemberVO"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%--
1. 디렉티브(Directive)에 대하여
JSP 페이지에 대한 설정정보를 지정할 때 사용된다. (page, taglib, include 등)
ex) <%@ 디렉티브이름 속성명="속성값" ... %>
2. 스크립트 요소에 대하여...
JSP에서 문서의 내용을 동적으로 생성하기 위해 사용된다.
- 표현식 (expression) : 값을 출력결과에 포함시키고자 할 때 사용된다. ex) <%=값%>
- 스크립트릿 (scriptlet) : 자바코드 블럭을 작성할 때 사용한다. ex> <% 자바코드들... %>
- 선언부 (declaration) : 스크립트릿이나 표현식에서 사용할 수 있는 메서드 작성시 사용한다. ㅏex <%! ~~~ %>
3. JSP 기본객체와 영역(SCOPE)
- PAGE : 하나의 JSP페이지를 처리할 때 사용되는 영역 => pageContext
- REQUEST : 하나의 HTTP요청을 처리할 때 사용되는 영역 => request
- SESSION : 하나의 브라우저(사용자)와 관련된 영역 => session
- APPLICATION : 하나의 웹애플리케이션과 관련된 영역 => application
--%>
<%
List<MemberVO> memList = (List<MemberVO>) request.getAttribute("memList");
// sendRedirect로 받아올 때 msg를 읽는 법
// String msg = request.getParameter("msg") == null ? ""
// : (String)request.getParameter("msg");
// 위의 방식이 아닌 session으로 작동 가능
String msg = session.getAttribute("msg") == null ? ""
: (String)session.getAttribute("msg");
session.removeAttribute("msg");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원목록</title>
</head>
<body>
<table border="1">
<tr>
<th>ID</th>
<th>이름</th>
<th>전화번호</th>
<th>주소</th>
<th>첨부파일</th>
</tr>
<%
if(memList.size() > 0) {
for(MemberVO mv : memList) {
%>
<tr>
<td><%=mv.getMemId()%></td>
<td><a href="./detail.do?memId=<%=mv.getMemId()%>"><%=mv.getMemName()%></a></td>
<td><%=mv.getMemTel()%></td>
<td><%=mv.getMemAddr()%></td>
<td><%=mv.getAtchFileId()%></td>
</tr>
<%
}
} else {
%>
<tr>
<td colspan="5">회원정보가 존재하지 않습니다.</td>
</tr>
<%
}
%>
<tr align="center">
<td colspan="5"><a href="<%=request.getContextPath()%>/member/insert.do">[회원 등록]</a></td>
</tr>
</table>
<%if(!msg.equals("")) {%>
<script>
alert('정상적으로 처리 되었습니다.');
</script>
<%}%>
</body>
</html>
insertForm.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>
<form action="./insert.do" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>I D:</td>
<td><input type="text" name="memId" value=""></td>
</tr>
<tr>
<td>이름:</td>
<td><input type="text" name="memName" value=""></td>
</tr>
<tr>
<td>전화번호:</td>
<td><input type="text" name="memTel" value=""></td>
</tr>
<tr>
<td>주소:</td>
<td><textarea name="memAddr" ></textarea></td>
</tr>
<tr>
<td>첨부파일</td>
<td><input type="file" name="atchFile" multiple="multiple" /></td>
</tr>
</table>
<input type="submit" value="회원 등록">
</form>
</body>
</html>
- 회원 상세 보기 시 파일 확인 및 회원 정보 수정 시 파일 재업로드
detail.jsp
<%@page import="kr.or.ddit.common.vo.AtchFileVO"%>
<%@page import="java.util.List"%>
<%@page import="kr.or.ddit.member.vo.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
MemberVO mv = (MemberVO) request.getAttribute("mv");
List<AtchFileVO> atchFileList =
(List<AtchFileVO>)request.getAttribute("atchFileList");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 정보 상세</title>
</head>
<body>
<table border="1">
<tr>
<td>I D:</td>
<td><%=mv.getMemId()%></td>
</tr>
<tr>
<td>이름:</td>
<td><%=mv.getMemName()%></td>
</tr>
<tr>
<td>전화번호:</td>
<td><%=mv.getMemTel()%></td>
</tr>
<tr>
<td>주소:</td>
<td><%=mv.getMemAddr()%></td>
</tr>
<tr>
<td>첨부파일:</td>
<td>
<%if(atchFileList != null) {
for(AtchFileVO fileVO : atchFileList) {
%>
<div><a href="#"><%=fileVO.getOrignlFileNm()%></a></div>
<%
}
}
%>
</td>
</tr>
<tr>
<td colspan="2">
<a href="./list.do">[목록]</a>
<a href="./update.do?memId=<%=mv.getMemId()%>">[회원정보 수정]</a>
<a href="<%=request.getContextPath()%>/member/delete.do?memId=<%=mv.getMemId()%>">[회원정보 삭제]</a>
</td>
</tr>
</table>
</body>
</html>
DetailMemberController.java
package kr.or.ddit.member.controller;
import java.io.IOException;
import java.util.List;
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 kr.or.ddit.common.service.AtchFileServiceImpl;
import kr.or.ddit.common.service.IAtchFileService;
import kr.or.ddit.common.vo.AtchFileVO;
import kr.or.ddit.member.service.IMemberService;
import kr.or.ddit.member.service.MemberServiceImpl;
import kr.or.ddit.member.vo.MemberVO;
@WebServlet("/member/detail.do")
public class DetailMemberController extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String memId = req.getParameter("memId");
IMemberService memService = MemberServiceImpl.getInstance();
MemberVO mv = memService.getMember(memId);
req.setAttribute("mv", mv);
if(mv.getAtchFileId() > 0) { // 첨부파일이 있는 경우
IAtchFileService fileService = AtchFileServiceImpl.getInstance();
AtchFileVO atchFileVO = new AtchFileVO();
atchFileVO.setAtchFileId(mv.getAtchFileId());
List<AtchFileVO> atchFileList = fileService.getAtchFileList(atchFileVO);
req.setAttribute("atchFileList", atchFileList);
}
req.getRequestDispatcher("/views/member/detail.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
RegistMemberController.java
package kr.or.ddit.member.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.or.ddit.common.service.AtchFileServiceImpl;
import kr.or.ddit.common.service.IAtchFileService;
import kr.or.ddit.common.vo.AtchFileVO;
import kr.or.ddit.member.service.IMemberService;
import kr.or.ddit.member.service.MemberServiceImpl;
import kr.or.ddit.member.vo.MemberVO;
@WebServlet("/member/insert.do")
@MultipartConfig
public class RegistMemberController extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/views/member/insertForm.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String memId = req.getParameter("memId");
String memName = req.getParameter("memName");
String memTel = req.getParameter("memTel");
String memAddr = req.getParameter("memAddr");
IMemberService memService = MemberServiceImpl.getInstance();
IAtchFileService fileService = AtchFileServiceImpl.getInstance();
AtchFileVO atchFileVO = new AtchFileVO();
try {
// 첨부파일 업로드 처리하기
atchFileVO = fileService.saveAtchFileList(req.getParts());
} catch (Exception e) {
e.printStackTrace();
}
MemberVO mv = new MemberVO(memId, memName, memTel, memAddr);
mv.setAtchFileId(atchFileVO.getAtchFileId());
int cnt = memService.registMember(mv);
String msg = "";
if(cnt > 0) {
// 삭제 성공
msg = "성공";
} else {
// 삭제 실패
msg = "실패";
}
req.getSession().setAttribute("msg", msg);
resp.sendRedirect(req.getContextPath() + "/member/list.do"); // 리다이렉트 처리...
}
}
ModifyMemberController.java
package kr.or.ddit.member.controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.or.ddit.common.service.AtchFileServiceImpl;
import kr.or.ddit.common.service.IAtchFileService;
import kr.or.ddit.common.vo.AtchFileVO;
import kr.or.ddit.member.service.IMemberService;
import kr.or.ddit.member.service.MemberServiceImpl;
import kr.or.ddit.member.vo.MemberVO;
@WebServlet("/member/update.do")
@MultipartConfig
public class ModifyMemberController extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String memId = req.getParameter("memId");
IMemberService memService = MemberServiceImpl.getInstance();
MemberVO mv = memService.getMember(memId);
req.setAttribute("mv", mv);
if(mv.getAtchFileId() > 0) { // 첨부파일이 있는 경우
IAtchFileService fileService = AtchFileServiceImpl.getInstance();
AtchFileVO atchFileVO = new AtchFileVO();
atchFileVO.setAtchFileId(mv.getAtchFileId());
List<AtchFileVO> atchFileList = fileService.getAtchFileList(atchFileVO);
req.setAttribute("atchFileList", atchFileList);
}
req.getRequestDispatcher("/views/member/updateForm.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String memId = req.getParameter("memId");
String memName = req.getParameter("memName");
String memTel = req.getParameter("memTel");
String memAddr = req.getParameter("memAddr");
String atchFileId = req.getParameter("atchFileId");
IMemberService memService = MemberServiceImpl.getInstance();
IAtchFileService fileService = AtchFileServiceImpl.getInstance();
AtchFileVO atchFileVO = new AtchFileVO();
try {
// 첨부파일 업로드 처리하기
atchFileVO = fileService.saveAtchFileList(req.getParts());
} catch (Exception e) {
e.printStackTrace();
}
MemberVO mv = new MemberVO(memId, memName, memTel, memAddr);
if(atchFileVO == null) { // 새로운 첨부파일이 없는 경우
mv.setAtchFileId(Long.parseLong(atchFileId)); // 기존 첨부파일 유지...
} else { // 새로운 첨부파일이 존재하는 경우...
mv.setAtchFileId(atchFileVO.getAtchFileId());
}
int cnt = memService.modifyMember(mv);
String msg = "";
if(cnt > 0) {
// 삭제 성공
msg = "성공";
} else {
// 삭제 실패
msg = "실패";
}
req.getSession().setAttribute("msg", msg);
resp.sendRedirect(req.getContextPath() + "/member/list.do"); // 리다이렉트 처리...
}
}
updataForm.jsp
<%@page import="kr.or.ddit.common.vo.AtchFileVO"%>
<%@page import="java.util.List"%>
<%@page import="kr.or.ddit.member.vo.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
MemberVO mv = (MemberVO)request.getAttribute("mv");
List<AtchFileVO> atchFileList =
(List<AtchFileVO>)request.getAttribute("atchFileList");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원정보 변경</title>
</head>
<body>
<form action="./update.do" method="post" enctype="multipart/form-data">
<input type="hidden" name="memId" value="<%=mv.getMemId()%>">
<input type="hidden" name="atchFileId" value="<%=mv.getAtchFileId()%>">
<table>
<tr>
<td>I D:</td>
<td><%=mv.getMemId()%></td>
</tr>
<tr>
<td>이름:</td>
<td><input type="text" name="memName" value="<%=mv.getMemName()%>"></td>
</tr>
<tr>
<td>전화번호:</td>
<td><input type="text" name="memTel" value="<%=mv.getMemTel()%>"></td>
</tr>
<tr>
<td>주소:</td>
<td><textarea name="memAddr" ><%=mv.getMemAddr()%></textarea></td>
</tr>
<tr>
<td>기존 첨부파일:</td>
<td>
<%if(atchFileList != null) {
for(AtchFileVO fileVO : atchFileList) {
%>
<div><a href="#"><%=fileVO.getOrignlFileNm()%></a></div>
<%
}
}
%>
</td>
</tr>
<tr>
<td>새로운 첨부파일</td>
<td><input type="file" name="atchFile" multiple="multiple"></td>
</tr>
</table>
<input type="submit" value="회원정보 수정">
</form>
</body>
</html>
- 파일 다운로드 할 수 있는 경우
- Content-Disposition
응답메시지의 Header에서 사용되는 경우... ex)파일 다운로드
사용법 | 뜻 |
inline | default Content를 브라우저 내에서 처리한다는 뜻 |
attachment | 파일 다운로드 처리 |
attachment; filename="hello.jpg" | 파일 다운로드 처리 다운 시 파일 이름 강제로 지정 가능 |
DownloadController.java
package kr.or.ddit.common.controller;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
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;
import kr.or.ddit.common.service.AtchFileServiceImpl;
import kr.or.ddit.common.service.IAtchFileService;
import kr.or.ddit.common.vo.AtchFileVO;
@WebServlet("/download.do")
public class DownloadController extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
long atchFileId = req.getParameter("fileId") == null ? -1
: Long.parseLong(req.getParameter("fileId"));
int fileSn = req.getParameter("fileSn") == null ? 1
: Integer.parseInt(req.getParameter("fileSn"));
// 파일 상세정보 조회
IAtchFileService fileService = AtchFileServiceImpl.getInstance();
AtchFileVO atchFileVO = new AtchFileVO();
atchFileVO.setAtchFileId(atchFileId);
atchFileVO.setFileSn(fileSn);
atchFileVO = fileService.getAtchFileDetail(atchFileVO);
///////////////////////////////////////////////////
// 파일 다운로드 처리를 위한 응답헤더 정보 설정하기
resp.setContentType("application/octet-stream");
resp.setHeader("Content-Disposition", "attachment; filename=\""
// URL에는 공백문자를 포함할 수 없다. URLEncoding을 이용하여 인코딩 작업을 사면
// 공백문자는 (+)로 표시되기 때문에 + 문자를 공백문자인 %20으로 바꿔준다.
+ URLEncoder.encode(atchFileVO.getOrignlFileNm(), "UTF-8")
.replaceAll("\\+", "%20")
+ "\"");
BufferedInputStream bis =
new BufferedInputStream(
new FileInputStream(atchFileVO.getFileStreCours()));
BufferedOutputStream bos = new BufferedOutputStream(resp.getOutputStream());
int data = 0;
while((data = bis.read()) != -1) {
bos.write(data);
}
bis.close();
bos.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
detail.jsp
<%@page import="kr.or.ddit.common.vo.AtchFileVO"%>
<%@page import="java.util.List"%>
<%@page import="kr.or.ddit.member.vo.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
MemberVO mv = (MemberVO) request.getAttribute("mv");
List<AtchFileVO> atchFileList =
(List<AtchFileVO>)request.getAttribute("atchFileList");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 정보 상세</title>
</head>
<body>
<table border="1">
<tr>
<td>I D:</td>
<td><%=mv.getMemId()%></td>
</tr>
<tr>
<td>이름:</td>
<td><%=mv.getMemName()%></td>
</tr>
<tr>
<td>전화번호:</td>
<td><%=mv.getMemTel()%></td>
</tr>
<tr>
<td>주소:</td>
<td><%=mv.getMemAddr()%></td>
</tr>
<tr>
<td>첨부파일:</td>
<td>
<%if(atchFileList != null) {
for(AtchFileVO fileVO : atchFileList) {
%>
<div><a href="<%=request.getContextPath()%>/download.do?fileId=<%=fileVO.getAtchFileId()%>&fileSn=<%=fileVO.getFileSn()%>"><%=fileVO.getOrignlFileNm()%></a></div>
<%
}
}
%>
</td>
</tr>
<tr>
<td colspan="2">
<a href="./list.do">[목록]</a>
<a href="./update.do?memId=<%=mv.getMemId()%>">[회원정보 수정]</a>
<a href="<%=request.getContextPath()%>/member/delete.do?memId=<%=mv.getMemId()%>">[회원정보 삭제]</a>
</td>
</tr>
</table>
</body>
</html>
- 로그인 기능 추가
로그인 기능 추가를 위해 MYMEMBER테이블을 이용한다.
LoginController.java
package kr.or.ddit.common.controller;
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 kr.or.ddit.member.dao.IMemberDao;
import kr.or.ddit.member.service.IMemberService;
import kr.or.ddit.member.service.MemberServiceImpl;
import kr.or.ddit.member.vo.MemberVO;
@WebServlet("/login.do")
public class LoginController extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/views/login/loginForm.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
IMemberService memService = MemberServiceImpl.getInstance();
// 해당 회원정보 가져오기
MemberVO mv = memService.getMember(username);
// DB에서 가져온 사용자 정보를 이용하여 패스워드 일치여부 확인
boolean isAuthenticated = false; // 인증된 사용자 여부
if(mv != null) {
if(password.equals(mv.getMemPass())) {
isAuthenticated = true;
}
}
if(isAuthenticated) { // 사용자 인증 성공시...
// 세션에 로그인 정보 설정하기
req.getSession().setAttribute("LOGIN_USER", mv);
// 메인페이지 이동...
resp.sendRedirect(req.getContextPath() + "/main.do");
} else { // 사용자 인증 실패시...
// 로그인 화면으로 이동..
resp.sendRedirect(req.getContextPath() + "/login.do");
}
}
}
loginForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>로그인 화면</title>
<link
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M"
crossorigin="anonymous">
<link
href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css"
rel="stylesheet" crossorigin="anonymous" />
</head>
<body>
<div class="container">
<form class="form-signin" method="post"
action="<%=request.getContextPath()%>/login.do">
<h2 class="form-signin-heading">Please sign in</h2>
<p>
<label for="username" class="sr-only">Username</label> <input
type="text" id="username" name="username" class="form-control"
placeholder="Username" required autofocus>
</p>
<p>
<label for="password" class="sr-only">Password</label> <input
type="password" id="password" name="password" class="form-control"
placeholder="Password" required>
</p>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign
in</button>
</form>
</div>
</body>
</html>
MemberVO.java
package kr.or.ddit.member.vo;
import java.time.LocalDate;
/**
* DB 테이블에 있는 컬럼명을 기준으로 데이터를 객체화 하기 위한 클래스
* <p>
* DB테이블의 컬럼과 클래스의 멤버변수를 매핑하는 역할을 수행한다.
* </p>
* @author PC-10
*
*/
public class MemberVO {
private String memId;
private String memPass;
private String memName;
private String memTel;
private String memAddr;
private LocalDate regDt;
private long atchFileId = -1;
public MemberVO(String memId, String memName, String memTel, String memAddr) {
this.memId = memId;
this.memName = memName;
this.memTel = memTel;
this.memAddr = memAddr;
}
public MemberVO() {
}
public String getMemPass() {
return memPass;
}
public void setMemPass(String memPass) {
this.memPass = memPass;
}
public long getAtchFileId() {
return atchFileId;
}
public void setAtchFileId(long atchFileId) {
this.atchFileId = atchFileId;
}
public String getMemId() {
return memId;
}
public void setMemId(String memId) {
this.memId = memId;
}
public String getMemName() {
return memName;
}
public void setMemName(String memName) {
this.memName = memName;
}
public String getMemTel() {
return memTel;
}
public void setMemTel(String memTel) {
this.memTel = memTel;
}
public String getMemAddr() {
return memAddr;
}
public void setMemAddr(String memAddr) {
this.memAddr = memAddr;
}
public LocalDate getRegDt() {
return regDt;
}
public void setRegDt(LocalDate regDt) {
this.regDt = regDt;
}
@Override
public String toString() {
return "MemberVO [memId=" + memId + ", memName=" + memName + ", memTel=" + memTel + ", memAddr=" + memAddr
+ "]";
}
}
MainControll.java
package kr.or.ddit.common.controller;
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("/main.do")
public class MainController extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/views/main.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
main.jsp
<%@page import="kr.or.ddit.member.vo.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
MemberVO mv = (MemberVO) session.getAttribute("LOGIN_USER");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>메인페이지</title>
</head>
<body>
<%
if(mv != null) {
%>
<p>반갑습니다. <%=mv.getMemName()%>님! <a href="<%=request.getContextPath()%>/logout.do">로그아웃</a>
<%
} else {
%>
<p> 아직 로그인을 하지 않으셨군요... 먼저 로그인 해 주세요... <a href="<%=request.getContextPath()%>/login.do">로그인</a></p>
<%
}
%>
</body>
</html>
'자바' 카테고리의 다른 글
[Java 고급] 33장 회원 관리 문제 (0) | 2024.04.03 |
---|---|
[Java 고급] 31장 파일 첨부 (0) | 2024.02.26 |
[Java 고급] 30장 서블릿 예시 (0) | 2024.02.22 |
[Java 고급] 29장 서블릿 컨텍스트, 필터, 리스너 (0) | 2024.02.22 |
[Java 고급] 28장 세션 (1) | 2024.02.21 |