서블릿웹앱 파일업로드

서현서현·2022년 5월 26일
0

서블릿 & JSP

목록 보기
17/26

보내는건 무조건 post로

멀티파트폼데이터 방식(전체바디를 파트로 구분하는 방법) 이용해서 보내야 효율적으로 파일 보낼 수 있음

서버에서 이걸 어떻게 처리하는지 ? ⇒ 아파치에서 모듈을 만들어놨다 = 파일업로드 모듈! (jar파일 갖다놓고 제공해주는 서블릿파일업로드, 리퀘스트파일 웅앵ㅇ? 해서 파싱해주기, 파일아이템을 다 꺼내서 메소드가 폼필드냐아니냐(아이템객체.isFoemField())해서 벨류값 꺼내서 폼필드가 아니면 멀티파트가 파일이라는거고 그럼 파일 이름을 알아내야됨(File객체.getName())이제 그 이름을 바탕으로 어떤파일을 업로드했는지 알았으니 그 내용, 즉 바이너리데이터를 저장해줘야됨 디스크에! 업로드는 File객체.upload()인가 이거 써주면 됨

서블릿3.0 이상의 톰캣 이용하는 WAS프로그램은 모두 이걸 쓰면 파일업로드 모듈을 따로 추가하지않아도 파일업로드를 할 수 있음! 기본적으로 개념이 달라진건 map으로 모두확인(?) 파트라는 인터페이스를 설계해서 파트단위로 운용할수있도록 해놈. 리퀘스트로부터 파트를 꺼내와(request.getParts())서 업로드 처리를 하면된다. write를 이용해서 업데이트 시켰다

어태치파일엔 ㅇ태치파일의 키값을 저장? 어태치파일 하나당 관리하기 위해 키를 잡아서 디테일태그도 만들었음 어태치파일 알고이으면 디테일 테이블 뒤져서 파일목록을 얻어올 수 있다

데베 연결

/* 첨부파일 테이블용 시퀀스 생성 */
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 '파일크기';

Untitled

Untitled

1. atchFile.xml 작성

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
			PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
			"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="atchFile">

	<select id="getAttchFileList" parameterClass="kr.or.ddit.comm.vo.AtchFileVO"
		resultMap="atchFileDetailMap">
		
		select * from atch_file_detail
		where atch_file_id = #atchFileId#
	
	</select>

2.AtchFileVO

import java.util.Date;

public class AtchFileVO {

	private long atchFileId = -1; // 첨부파일 ID
	private Date crearDt; //생성일자
	private int fileSn = 1; // 파일순번
	private String fileStreCours; // 파일저장경로
	private String streFileNm; // 저장파일명
	private String orignlFileNm; // 원본파일명
	private String fileExtsn; // 파일확장자
	private String fileCn; // 파일내용
	
	public long getAtchFileId() {
		return atchFileId;
	}
	public void setAtchFileId(long atchFileId) {
		this.atchFileId = atchFileId;
	}
	public Date getCrearDt() {
		return crearDt;
	}
	public void setCrearDt(Date crearDt) {
		this.crearDt = crearDt;
	}
	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;
	}
	private long fileSize = 0; //파일크기

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
			PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
			"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="atchFile">
	
	<resultMap class ="kr.or.ddit.comm.vo.AtchFileVO" id="atchFileDetailMap">
	
		<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>
	
	<select id="getAttchFileList" parameterClass="kr.or.ddit.comm.vo.AtchFileVO"
		resultMap="atchFileDetailMap">
		
		select from atch_file_detail
		where atch_file_id = #atchFileId#
	
	</select>
	
	<select id="getAtchFileDetail" parameterClass="kr.or.ddit.comm.vo.AtchFileVO"
		resultMap="atchFileDetailMap">
		
		select from atch_file_detail
		where atch_file_id = #atchFileId#
			and file_sn = #fileSn#
	
	</select>
	
	<insert id = "insertAtchFile" parameterClass="kr.or.ddit.comm.vo.AtchFileVO">
	<!-- 셀렉트키가 주는 장점...  -->
		<selectKey keyProperty="atchFileId" resultClass="long">
			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
	(
	/**/ There is no READABLE property named 어쩌구 에러**
	**// 미쳤다...... 공백 주의 ##사이엔 공백 절대 넣지 말것!!!**
	#atchFileId#
	,(select nvl(max(file_sn),0)+1
		from atch_file_detail
		where atch_file_id = #atchFileId#)
	,#fileStreCours#
	,#streFileNm#
	,#orignlFileNm#
	,#fileExtsn#
	,#fileCn#
	,#fileSize#
	)
	</insert>
	
</sqlMap>

DAO인터페이스

smc는 서비스단에서 만들어 넣어주는 식으로 하자 (트랜잭션을 고려했음)

import java.util.List;

import com.ibatis.sqlmap.client.SqlMapClient;

import kr.or.ddit.comm.vo.AtchFileVO;

public interface IAtchFileDAO {

	/**
	 * 첨부파일 저장
	 * @param atchFileVO
	 * @return
	 */
	public long insertAtchFile(SqlMapClient smc, AtchFileVO atchFileVO);
	
	/**
	 * 첨부파일 세부정보 저장
	 * @param atchFileVO
	 * @return
	 */
	public int  insertAtchFileDetail(SqlMapClient smc, AtchFileVO atchFileVO);
	
	/**
	 * 첨부파일 목록 조회
	 * @param atchFileVO
	 * @return
	 */
	public List<AtchFileVO> getAtchFileList(SqlMapClient smc, AtchFileVO atchFileVO);
	
	
	/**
	 * 첨부파일 세부정보 조회메소드
	 * @param atchFileVO 검색할 첨부파일 정보(아이디 및 순번)
	 * @return
	 */
	public AtchFileVO getAtchFileDetail(SqlMapClient smc, AtchFileVO atchFileVO);
	
}

DAO임플리먼트

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.ibatis.sqlmap.client.SqlMapClient;

import kr.or.ddit.comm.vo.AtchFileVO;

public class AtchFileDAOImpl implements IAtchFileDAO{

	private static IAtchFileDAO dao;
	
	private AtchFileDAOImpl() {
		// TODO Auto-generated constructor stub
	}
	
	public static IAtchFileDAO getInstance() {
		if(dao==null) {
			dao=new AtchFileDAOImpl();
		}
		return dao;
	}
	
@Override
	public long insertAtchFile(SqlMapClient smc, AtchFileVO atchFileVO) {
		
		long cnt=0;
		try {
			cnt = (long)(smc.insert("atchFile.insertAtchFile",atchFileVO));
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException("첨부파일 저장중 예외 발생",e);
		}
		return cnt; // insert의 경우 select키 사용시 서비스에서 리턴값 안쓸건데 일단 걍 만들었음 
		
	}

	@Override
	public int insertAtchFileDetail(SqlMapClient smc, AtchFileVO atchFileVO) {
		int cnt=0;
		try {
			
			Object obj = (smc.insert("atchFile.insertAtchFileDetail",atchFileVO));
			// null이나오니까 int캐스팅 ㄴㄴ
			if(obj == null) {
				cnt=1;
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException("첨부파일 세부정보 저장중 예외 발생",e);
		}
		// 셀렉트 안한경우에는 늘 null... 과거엔 null이면 성공 실패로 했었음..
		return cnt; 
	}

	@Override
	public List<AtchFileVO> getAtchFileList(SqlMapClient smc, AtchFileVO atchFileVO) {
		List<AtchFileVO> atchFileList= new ArrayList<AtchFileVO>();
		try {
			atchFileList= smc.queryForList("atchFile.getAttchFileList",atchFileVO);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException("첨부파일 목록 조회중 예외발생",e);
		}
		
		return atchFileList;
	}

	@Override
	public AtchFileVO getAtchFileDetail(SqlMapClient smc, AtchFileVO atchFileVO) {
		AtchFileVO fileVO = new AtchFileVO();
		
		try {
			fileVO = (AtchFileVO) smc.queryForObject("atchFile.getAtchFileDetail",atchFileVO);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException("첨부파일 세부정보 조회중 예외발생",e);
		}
		return fileVO;
	}

}

Service 인터페이스

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import kr.or.ddit.comm.vo.AtchFileVO;

public interface IAtchFileService {
	
	/**
	 * 첨부파일 목록을 저장하기 위한 메소드
	 * @param req Part정보를 꺼내기 위한 요청객체
	 * @return AtchFileVO 저장한 첨부파일 정보
	 */
	public AtchFileVO saveAtchFileList(HttpServletRequest req);
	
	
	/**
	 * 첨부파일 목록 조회
	 * @param atchFileVO
	 * @return
	 */
	public List<AtchFileVO> getAtchFileList(AtchFileVO atchFileVO);
	
	

	/**
	 * 첨부파일 세부정보 조회하기
	 * @param atchFileVO
	 * @return
	 */
	public AtchFileVO getAtchFileDetail(AtchFileVO atchFileVO);
	
	
	// 서비스단에서는 부모자식 각각 호출 필요 없음! 그래서 일단 세개의 메소드만
}

Service임플리먼트

private static final String UPLOAD_DIR = "upload_files"; 추가하고
@Override
	public AtchFileVO saveAtchFileList(HttpServletRequest req) {
		
		String uploadPath = req.getServletContext().getRealPath("/")
				+ File.separator + UPLOAD_DIR;
		
		File uploadDir = new File(uploadPath);
		
		if(! uploadDir.exists()) { //업로드 경로 존재하지 않으면
			uploadDir.mkdir();
		}
		
		AtchFileVO atchFileVO = null;
		
		try {
			String fileName = "";
			
			boolean isFirstFile = true; //첫번째 파일여부 체크
			
			for(Part part : req.getParts()) {
				fileName = getFileName(part); //파일명추출
				
				if(fileName != null && !fileName.equals("")) {
					// 파일 이름이 존재한다 = 파일이 첨부되었다
					// 파일이름이 empty = 타입이 file인 인풋태그를 취소 누르고 보내면 파일이름은 존재하나 emptyString
					if(isFirstFile) { //첫번째 파일정보에 접근하기
						isFirstFile = false;
						
						//파일 기본정보 저장하기
						atchFileVO = new AtchFileVO();
						
						//기본 첨부파일정보 저장(VO에 atchFileId가 저장됨)
						// 즉 파라미터로 넣은 atchFileVO가 아이디값이 세팅되어있음
						// 아이바티스가 작업해서 꽂아준 객체가 이 객체인거임
						// 따라서 insert가 제대로 실행되면 nextval로 세팅된 키값이 세팅이 완료되는것. 디테일에서 쓸수있다
						fileDao.insertAtchFile(smc, atchFileVO);
						
					}
					
					String orignFileName = fileName; //원본파일
					long fileSize = part.getSize(); //파일사이즈
					String saveFileName = ""; //저장파일명
					String saveFilePath =""; //저장 파일경로
					File storeFile = null; //저장파일객체
					
					do {
						saveFileName = UUID.randomUUID().toString().replace("-", "");
						saveFilePath = uploadPath + File.separator + saveFileName;
						System.out.println("저장파일경로: "+saveFileName);
						storeFile = new File(saveFilePath);
					} while (storeFile.exists());
					
					// 확장명 추출
					String fileExtension = 
							orignFileName.lastIndexOf(".") < 0 ? 
									"" : orignFileName.substring(
											orignFileName.lastIndexOf(".")+1);
					
					part.write(saveFileName); // 업로드 파일 저장
					
					atchFileVO.setStreFileNm(saveFileName);;
					atchFileVO.setFileSize(fileSize);
					atchFileVO.setOrignlFileNm(orignFileName);
					atchFileVO.setFileStreCours(saveFilePath);
					atchFileVO.setFileExtsn(fileExtension);
					
					// 파일 세부정보 저장
					fileDao.insertAtchFile(smc, atchFileVO);
					
					part.delete(); // 임시 저장 업로드 파일 삭제
					
					System.out.println("파일명 : "+fileName+ " 업로드 완료");
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return atchFileVO;
		// 인서트를 했다면 이 안에 atcnFileId가 들어있음
	}

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>

MYMEMBER테이블 컬럼(ATCH_FILE_ID)추가

Untitled

InsertMemberController

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.comm.service.AtchFileServiceImpl;
import kr.or.ddit.comm.service.IAtchFileService;
import kr.or.ddit.comm.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")
public class InsertMemberController extends HttpServlet{

	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.getRequestDispatcher("/view/member/insertForm.jsp").forward(req, resp);
	}
	
	
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 1. 요청파라미터 정보 가져오기
		String memId = req.getParameter("memId");
		String memName= req.getParameter("memName");
		String memTel = req.getParameter("memTel");
		String memAddr = req.getParameter("memAddr");
		
		// 2. 서비스 객체 생성하기
		IMemberService memService = MemberServiceImpl.getInstance();
		IAtchFileService fileService = AtchFileServiceImpl.getInstance();
		
		AtchFileVO atchFileVO = new AtchFileVO();
		
		// 첨부파일목록 저장(공통기능)
		atchFileVO = fileService.saveAtchFileList(req);
		
		// 3. 회원정보 등록
		MemberVO mv = new MemberVO();
		mv.setMemId(memId);
		mv.setMemName(memName);
		mv.setMemTel(memTel);
		mv.setMemAddr(memAddr);
		
		int cnt = memService.insertMember(mv);
		
		String msg = "";
		
		if(cnt>0) {
			msg = "성공";
		} else {
			msg="실패";
		}
		
		//req.getRequestDispatcher("/member/list.do").forward(req, resp);
		// 앞에 플젝네임을 만들어줄게 이거 안만들면 링크에서 안생겨서 404에러뜸
		String redirectUrl = req.getContextPath()+"/member/list.do";
		resp.sendRedirect(redirectUrl);
		
		
	}
}

MemberVO

추가

	private long atchFileId = -1;

	public long getAtchFileId() {
		return archFileId;
	}

Member.xml

다음을 추가

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
			PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
			"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="member">

	<insert id="insertMember" parameterClass="memVO">
	
		insert into mymember
		(mem_id,mem_name, mem_tel, mem_addr, **atch_file_id)**
		values(#memId#,#memName#,#memTel#,#memAddr#,**#atch_file_id#)**
	
	</insert>
	
	<update id="updateMember" parameterClass="memVO">
		update mymember
				set mem_name = #memName#,
					mem_tel = #memTel#,
					mem_addr = #memAddr#
					**atch_file_id = #atch_file_id#**
				where mem_id = #memId#
	</update>
	
	
	<delete id="deleteMember" parameterClass="String">
		delete from mymember
		where mem_id = #memId#
	</delete>
	

	
	<resultMap class="memVO" id="memMap">
		<result property="memId" column="mem_id"/>
		<result property="memName" column="mem_name"/>
		<result property="memTel" column="mem_tel"/>
		<result property="memAddr" column="mem_addr"/>
		**<result property="atchFileId" column="atch_file_id"/>**
	</resultMap>
	

</sqlMap>

Untitled

InsertMemberController

mv.setAtchFileId(atchFileVO.getAtchFileId());

+멀티파트도 처리해줘야함!

insertMemberController 상단에 추가

@MultipartConfig(fileSizeThreshold = 1024*1024*3, maxFileSize=1024*1024_40, maxRequestSize=1024*1024*50)

SQLMAP 잊지마

<sqlMap resource="sqlmap/member.xml"/>
	**<sqlMap resource="sqlmap/atchFile.xml"/>**

Untitled

Untitled

세부사항조회(?)

detail.jsp

<%@page import="java.util.List"%>
<%@page import="kr.or.ddit.comm.vo.AtchFileVO"%>
<%@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="delete.do?memId=<%=mv.getMemId() %>">[회원정보 삭제]</a>
			</td>
		</tr>
	</table>
</body>
</html>

Untitled

업로드한거 다운로드 받기

새로운 서블릿 - FileDownloadController 생성

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.coyote.http11.filters.BufferedInputFilter;

import kr.or.ddit.comm.service.AtchFileServiceImpl;
import kr.or.ddit.comm.service.IAtchFileService;
import kr.or.ddit.comm.vo.AtchFileVO;

public class FileDownloadController extends HttpServlet {
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		long fileId = req.getParameter("fileId") != null ?
				Long.parseLong(req.getParameter("fileId")) : -1;
				
		int fileSn = req.getParameter("fileSn") != null ?
				Integer.parseInt(req.getParameter("fileSn")) : 1;
				
		// 파일정보 조회
				
				IAtchFileService fileService = AtchFileServiceImpl.getInstance();
				
				AtchFileVO atchFileVO = new AtchFileVO();
				atchFileVO.setAtchFileId(fileId);
				atchFileVO.setFileSn(fileSn);
				
				atchFileVO = fileService.getAtchFileDetail(atchFileVO);
				
				// 파일다운로드 처리를 위한 응답헤더 정보 설정하기
				resp.setContentType("application/octet-stream");
				resp.setHeader("Content-Disposition","attachment; filename=\"" 
						+ atchFileVO.getOrignlFileNm() +"\"");
				
				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 {
		// TODO Auto-generated method stub
		super.doPost(req, resp);
	}

}

Untitled

어태치 파일아이디와 순번만 있으면 가능!!

🚨 파일경로 이상해서 수정 + 저장경로 변수명 잘못써서 수정함!!

import java.io.File;
import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;

import com.ibatis.sqlmap.client.SqlMapClient;

import kr.or.ddit.comm.dao.AtchFileDAOImpl;
import kr.or.ddit.comm.dao.IAtchFileDAO;
import kr.or.ddit.comm.vo.AtchFileVO;
import kr.or.ddit.util.sqlMapClientFactory;

public class AtchFileServiceImpl implements IAtchFileService {
	
	private static IAtchFileService service;
	private SqlMapClient smc;
	private IAtchFileDAO fileDao;
	private static final String UPLOAD_DIR = "d:/D_Other/upload_files";
	
	private AtchFileServiceImpl() {
		smc = sqlMapClientFactory.getInstance();
		fileDao = AtchFileDAOImpl.getInstance();
		
		
		
	}
	
	public static IAtchFileService getInstance() {
		if(service == null) {
			service = new AtchFileServiceImpl();
		}
		return service;
	}

	
	@Override
	public AtchFileVO saveAtchFileList(HttpServletRequest req) {
		/*
		 * String uploadPath = req.getServletContext().getRealPath("/") + UPLOAD_DIR;
		 */
		String uploadPath = UPLOAD_DIR;
		File uploadDir = new File(uploadPath);
		
		if(! uploadDir.exists()) { //업로드 경로 존재하지 않으면
			uploadDir.mkdir();
		}
		
		AtchFileVO atchFileVO = null;
		
		try {
			String fileName = "";
			
			boolean isFirstFile = true; //첫번째 파일여부 체크
			
			for(Part part : req.getParts()) {
				fileName = getFileName(part); //파일명추출
				
				if(fileName != null && !fileName.equals("")) {
					// 파일 이름이 존재한다 = 파일이 첨부되었다
					// 파일이름이 empty = 타입이 file인 인풋태그를 취소 누르고 보내면 파일이름은 존재하나 emptyString
					if(isFirstFile) { //첫번째 파일정보에 접근하기
						isFirstFile = false;
						
						//파일 기본정보 저장하기
						atchFileVO = new AtchFileVO();
						
						//기본 첨부파일정보 저장(VO에 atchFileId가 저장됨)
						// 즉 파라미터로 넣은 atchFileVO가 아이디값이 세팅되어있음
						// 아이바티스가 작업해서 꽂아준 객체가 이 객체인거임
						// 따라서 insert가 제대로 실행되면 nextval로 세팅된 키값이 세팅이 완료되는것. 디테일에서 쓸수있다
						fileDao.insertAtchFile(smc, atchFileVO);
						
					}
					
					String orignFileName = fileName; //원본파일
					long fileSize = part.getSize(); //파일사이즈
					String saveFileName = ""; //저장파일명
					String saveFilePath =""; //저장 파일경로
					File storeFile = null; //저장파일객체
					
					do {
						saveFileName = UUID.randomUUID().toString().replace("-", "");
						saveFilePath = uploadPath + File.separator + saveFileName;
						System.out.println("저장파일경로: "+saveFilePath);
						storeFile = new File(saveFilePath);
					} while (storeFile.exists());
					
					// 확장명 추출
					String fileExtension = 
							orignFileName.lastIndexOf(".") < 0 ? 
									"" : orignFileName.substring(
											orignFileName.lastIndexOf(".")+1);
					
					part.write(saveFilePath); // 업로드 파일 저장
					
					atchFileVO.setStreFileNm(saveFileName);;
					atchFileVO.setFileSize(fileSize);
					atchFileVO.setOrignlFileNm(orignFileName);
					atchFileVO.setFileStreCours(saveFilePath);
					atchFileVO.setFileExtsn(fileExtension);
					
					// 파일 세부정보 저장
					fileDao.insertAtchFileDetail(smc, atchFileVO);
					
					part.delete(); // 임시 저장 업로드 파일 삭제
					
					System.out.println("파일명 : "+fileName+ " 업로드 완료");
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return atchFileVO;
	
	}
	
	private String getFileName(Part part) {

		for(String content : part.getHeader("Content-Disposition").split(";")) {
			if(content.trim().startsWith("filename")) {
				return content.substring(content.indexOf("=")+1).trim().replace("\"", "");
			}
		}
		
		return null;
	}

	
	
	
	
	@Override
	public List<AtchFileVO> getAtchFileList(AtchFileVO atchFileVO) {
		return fileDao.getAtchFileList(smc, atchFileVO);		
	}

	@Override
	public AtchFileVO getAtchFileDetail(AtchFileVO atchFileVO) {
		return fileDao.getAtchFileDetail(smc, atchFileVO);
	}

}

Untitled

(쿼리를 포함한 url을 이용해서 드감)

이제 클릭하면 다운 되도록 할거임

디테일 JSP에 경로 추가

<div><a href="<%=request.getContextPath() %>/filedownload.do?fileId=<%=fileVO.getAtchFileId() %>&fileSn=<%=fileVO.getFileSn() %>"><%=fileVO.getOrignlFileNm() %></a></div>

다운로드시 파일 이름이 한글이면 제대로뜨지않음........

→ 인코딩 처리 필요

파일 다운로드 콘트롤러

// 파일다운로드 처리를 위한 응답헤더 정보 설정하기
// URL에는 공백문자를 포함할 수 없다 URL Encoding을 이용하여 인코딩작업을 하면
// 공백은 (+)로 표시되기 때문에 (+)문자를 공백문자를 의미하는 %20으로 바꿔준다.
resp.setHeader("Content-Disposition","attachment; filename=\""  + URLEncoder.encode(atchFileVO.getOrignlFileNm(),"UTF-8").replaceAll("\\+", "%20")+"\"");

파일명에 스페이스 들어가늕거 처리해주려고....

update

업데이트폼 jsp

<%@page import="java.util.List"%>
<%@page import="kr.or.ddit.comm.vo.AtchFileVO"%>
<%@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"); //getPatameter()는 사용자가 던져준거니까 쓰면 안돼. 저장해둔 mv 쓰는거니까 getAttribute()
	
	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">
	<input type="hidden" name="memId" value="<%=mv.getMemId() %>"> <!-- submit했을때 id도 form에 실려 같이감 -->
		<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="<%=request.getContextPath() %>/filedownload.do?fileId=<%=fileVO.getAtchFileId() %>&fileSn=<%=fileVO.getFileSn() %>"><%=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>

업데이트 멤버 컨트롤러

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.comm.service.AtchFileServiceImpl;
import kr.or.ddit.comm.service.IAtchFileService;
import kr.or.ddit.comm.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")
public class UpdateMemberController extends HttpServlet{

	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		String memId = req.getParameter("memId");
		
		// 1. 서비스 객체 생성하기
		IMemberService memService = MemberServiceImpl.getInstance();
		IAtchFileService fileService = AtchFileServiceImpl.getInstance();
		
		// 2. 회원정보 조회
		MemberVO mv = memService.getMember(memId);
		
		
				
		if(mv.getAtchFileId()>0) { // 첨부파일 존재하는 경우...
			// 2-1. 첨부파일 목록 조회
			AtchFileVO fileVO = new AtchFileVO();
			fileVO.setAtchFileId(mv.getAtchFileId());
			
			List<AtchFileVO> atchFileList = fileService.getAtchFileList(fileVO);
			
			req.setAttribute("atchFileList", atchFileList);
		}
				
				

		
		
		
		
		
		
		req.setAttribute("mv", mv);
		
		req.getRequestDispatcher("/view/member/updateForm.jsp").forward(req, resp); //jsp는 이제 mv를 갖다가 화면울 구성 할 수 있겠지?
		
	}
	
	
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 1. 요청파라미터 정보 가져오기
		String memId = req.getParameter("memId");
		String memName= req.getParameter("memName");
		String memTel = req.getParameter("memTel");
		String memAddr = req.getParameter("memAddr");
		
		// 2. 서비스 객체 생성하기
		IMemberService memService = MemberServiceImpl.getInstance();
		
		// 3. 회원정보 변경
		MemberVO mv = new MemberVO();
		mv.setMemId(memId);
		mv.setMemName(memName);
		mv.setMemTel(memTel);
		mv.setMemAddr(memAddr);
		
		int cnt = memService.updateMember(mv);
		
		String msg = "";
		
		if(cnt>0) {
			msg = "성공";
		} else {
			msg="실패";
		}
		
		//req.getRequestDispatcher("/member/list.do").forward(req, resp);
		// 앞에 플젝네임을 만들어줄게 이거 안만들면 링크에 플젝네임이 안생겨서 404에러뜸..
		String redirectUrl = req.getContextPath()+"/member/list.do";
		resp.sendRedirect(redirectUrl);
		
		
	}
}

Untitled

만약 파일을 바꾸지 않을떈 파일이 유지되어야함!

기존 첨부파일 아이디 참조할수있게 하도록 하자

업데이트폼jsp

<%@page import="java.util.List"%>
<%@page import="kr.or.ddit.comm.vo.AtchFileVO"%>
<%@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"); //getPatameter()는 사용자가 던져준거니까 쓰면 안돼. 저장해둔 mv 쓰는거니까 getAttribute()
	
	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() %>"> <!-- submit했을때 id도 form에 실려 같이감 -->
	**<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="<%=request.getContextPath() %>/filedownload.do?fileId=<%=fileVO.getAtchFileId() %>&fileSn=<%=fileVO.getFileSn() %>"><%=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>

업데이트 멤버 컨트롤러

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.comm.service.AtchFileServiceImpl;
import kr.or.ddit.comm.service.IAtchFileService;
import kr.or.ddit.comm.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(fileSizeThreshold = 1024*1024*3, maxFileSize=1024*1024_40, maxRequestSize=1024*1024*50)
public class UpdateMemberController extends HttpServlet{

	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		String memId = req.getParameter("memId");
		
		// 1. 서비스 객체 생성하기
		IMemberService memService = MemberServiceImpl.getInstance();
		IAtchFileService fileService = AtchFileServiceImpl.getInstance();
		
		// 2. 회원정보 조회
		MemberVO mv = memService.getMember(memId);
		
		
				
		if(mv.getAtchFileId()>0) { // 첨부파일 존재하는 경우...
			// 2-1. 첨부파일 목록 조회
			AtchFileVO fileVO = new AtchFileVO();
			fileVO.setAtchFileId(mv.getAtchFileId());
			
			List<AtchFileVO> atchFileList = fileService.getAtchFileList(fileVO);
			
			req.setAttribute("atchFileList", atchFileList);
		}
				
		req.setAttribute("mv", mv);
		
		req.getRequestDispatcher("/view/member/updateForm.jsp").forward(req, resp); //jsp는 이제 mv를 갖다가 화면울 구성 할 수 있겠지?
		
	}
	
	
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		
		
		
		
		
		// 1. 요청파라미터 정보 가져오기
		String memId = req.getParameter("memId");
		String memName= req.getParameter("memName");
		String memTel = req.getParameter("memTel");
		String memAddr = req.getParameter("memAddr");
		
		// 따로 첨부파일 올린적없으면 -1이 스트링으로 오고... 그래서 long임
		// 즉 기존 첨부파일에 대한 ID값
		long atchFileId = Long.parseLong(req.getParameter("atchFileId"));
		
		// 2. 서비스 객체 생성하기
		IMemberService memService = MemberServiceImpl.getInstance();
		IAtchFileService fileService = AtchFileServiceImpl.getInstance();
		
		AtchFileVO atchFileVO = new AtchFileVO();
		
		// 첨부파일목록 저장(공통기능)
		atchFileVO = fileService.saveAtchFileList(req);
		
		
		
		// 3. 회원정보 변경
		MemberVO mv = new MemberVO();
		mv.setMemId(memId);
		mv.setMemName(memName);
		mv.setMemTel(memTel);
		mv.setMemAddr(memAddr);
		
		
		if(atchFileVO != null) {
			mv.setAtchFileId(atchFileVO.getAtchFileId());
		} else {
			mv.setAtchFileId(atchFileId);
		}
		// 만약 아니라면 기존 atchFile 유지해야함!
		
		int cnt = memService.updateMember(mv);
		
		String msg = "";
		
		if(cnt>0) {
			msg = "성공";
		} else {
			msg="실패";
		}
		
		//req.getRequestDispatcher("/member/list.do").forward(req, resp);
		// 앞에 플젝네임을 만들어줄게 이거 안만들면 링크에 플젝네임이 안생겨서 404에러뜸..
		String redirectUrl = req.getContextPath()+"/member/list.do";
		resp.sendRedirect(redirectUrl);
		
		
	}
}

오류가 났는데 member.xml 파일에서 update쿼리에 콤마가 빠져있었다!

Untitled

Untitled

수정 잘된다

파일 여러개 선택해도 ㄱㅊ 그럼 데베에 순서대로 들어간당

Untitled

Untitled

이렇게!!

0개의 댓글