[Write]

writle.jsp파일부터 우선 bbs에서 복사해 옴
여기서도 스크립팅 요소는 싹 지우고 시작하자
여기서는 저번에 사용한 파일 업/다운로드를 이용할거임
자료실이니까 파일 업로드 하니까!
저번에 받은 model에 FileUtils에 메소드를 추가해서 사용할 것
파일을 업로는 하는 로직을 메소드로 빼서
필요할 때 간편하게 메소드만 호출 할 것임
그리고 만약 입력에 실패했을 때(용량이 크다거나 내용이 알맞지 않다거나)
업로드되는걸 막아야 하기 때문에 파일 삭제 로직도 추가
(이거 없으면 실패해도 그냥 업로드가 되버리더라!!)

인자로 part: 파일정보/ savedire : 물리적 경로 를 받는군....
public static String upload(Collection<Part> parts,String saveDirectory) {
    String filenames=" ";
        //업로드된 파일명들 저장용
    try {		
        for(Part part:parts) {
            if(part.getContentType() !=null) { //타입이 파일 일때만 contentType 이 있다. 					
                String systemFileName=FileUtils.getNewFileName(saveDirectory,part.getSubmittedFileName());									
                filenames+=systemFileName+",";				
                //파일 업로드(진짜 업로드 됨  ,File.separator는 운영체제따라 경로 사용할 따 \혹은/ 를 다르게 적용시켜줌 )
                part.write(saveDirectory+File.separator+systemFileName);
            }
        }
    }
    catch(Exception e) {
        return null ;
    }
    return filenames.substring(0,filenames.length()-1);
}/////////////////

//삭제로직
public static void deletes(String filenames,String saveDirectory) {
    String[] files = filenames.split(",");
    for(String filename: files) {
        File f =new File(saveDirectory+File.separator+filename);
        if(f.exists()) f.delete();
    }
}/////////////////


입력하는거니까 insert메소드 구현해야 겠지? 이번엔 컨트롤러 작성 전에
DAO에 insert메소드 작성을 먼저 해 보자

@Override
public int insert(DataRoomDTO dto) {
    int affected = 0;
    String sql ="INSERT INTO DATAROOM VALUES(SEQ_DATAROOM.NEXTVAL,?,?,?,?,?,DEFAULT,SYSDATE)";
    try {
        psmt = conn.prepareStatement(sql);
        psmt.setString(1, dto.getName());
        psmt.setString(2, dto.getPassword());
        psmt.setString(3, dto.getTitle());
        psmt.setString(4, dto.getContent());
        psmt.setString(5, dto.getAttachFile());
        affected = psmt.executeUpdate();
    } 
    catch(SQLException e) {e.printStackTrace();}
    return affected;
}////////////


wirtecontroller 만들기
하나의 컨트롤러로 두 가지 기능 처리
즉 GET방식 일 때는 입력폼으로 이동
POST방식 일 때는 입력 처리(get으로 받고 일처리는 post로 몰아주기)

@WebServlet("/DataRoom/Write.kosmo")
@MultipartConfig(maxFileSize = 1024*500,maxRequestSize = 1024*500*5)
public class WriteController extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//2]요청분석- 입력폼 요청
		//3]모델호출 및 결과값 받기
		//4]결과값이 있으면 ,리퀘스트 영역에 저장
		//5]뷰 선택
		req.getRequestDispatcher("/dataroom14/Write.jsp").forward(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		//DB입력 성공시에는 1, 실패시 0, 파일용량 초과시는 -1
		int insertflag;
		try { 
			 //서버의 물리적 경로 얻기
			String saveDirectory = req.getServletContext().getRealPath("/upload");
			//기타 파라미터 받기
			String name = req.getParameter("name");
			String title= req.getParameter("title");
			String password = req.getParameter("password");
			String content = req.getParameter("content");
			
			//업로드된 파일 정보를 얻기 위한 part객체 생성
			Collection<Part> parts=req.getParts();//요 메소드 호출 시 용량 초과하면 에러	
			//파일 업로드 로직 호출
			String filenames=FileUtils.upload(parts, saveDirectory);
			//나머지 받은 파람들 입력처리로직(데이터베이스 CRUD관련 작업 호출)
			DataRoomDAO dao = new DataRoomDAO(getServletContext());
			DataRoomDTO dto = new DataRoomDTO();
			dto.setAttachFile(filenames);
			dto.setContent(content);
			dto.setName(name);
			dto.setPassword(password);
			dto.setTitle(title);
			insertflag=dao.insert(dto);
			
			if(insertflag == 0) { // 입력실패시 업로드 된 파일 삭제로직 호출
				//파일 삭제 로직 호출
				FileUtils.deletes(filenames, saveDirectory);
			}			
		}
		catch (Exception e) { //파일용량 초과시
			insertflag=-1;
		}
		
		//메시지 뿌려주는 jsp페이지(insertFlag값 사용)로 이동 후 목록으로 이동
		//리퀘스트 영역에 결과값 혹은 필요한 값 저장
		//입력 시 성공여부
		req.setAttribute("SUCCFAIL", insertflag);
		//컨트롤러 구분용 -입력: ins,수정edt, 삭제del
		req.setAttribute("WHERE","INS");	
		///포워드
		req.getRequestDispatcher("/dataroom14/Message.jsp").forward(req, resp);
	}////
}

그러면 메시지를 만들러또 가야겠네
Message.jsp 얘는 새로생성
얘도 꼭
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 잊지말자!

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:choose>
	<c:when test="${WHERE =='INS'}">
		<c:set var="successMsg" value="입력 성공했어요"/>
		<c:set var="failMsg" value="입력 실패했어요"/>
		<c:set var="successUrl" value="/DataRoom/List.kosmo"/>
	</c:when>
	<c:when test="${WHERE =='EDT'}">
		<c:set var="successMsg" value="수정 성공했어요"/>
		<c:set var="failMsg" value="수정 실패했어요"/>
		<c:set var="successUrl" value="/DataRoom/View.kosmo?no=${no}"/>
	</c:when>
	<c:otherwise>
		<c:set var="successMsg" value="삭제 성공했어요"/>
		<c:set var="failMsg" value="삭제 실패했어요"/>
		<c:set var="successUrl" value="/DataRoom/List.kosmo"/>
	</c:otherwise>
</c:choose>

<script>
	<c:choose>
		<c:when test="${SUCCFAIL==1}">
			alert("${successMsg }");
			location.replace("<c:url value="${successUrl}"/>");
		</c:when>
		<c:when test="${SUCCFAIL==0}">
			alert("${failMsg}");
			history.back();
		</c:when>
		<c:otherwise>
			alert("파일 업로드 용량 초과")
			history.back();
		</c:otherwise>
	</c:choose>		
</script>

이래서 자바스크립트도 손을 놓을 수가 없구나

최종 write.jsp에서 받은값들 뿌려주고
등록처리하기
처리할게.. 너무 많아서 ...
맨 위에 taglib 꼭 넣고!!
경고 메시지 넣어
<c:if test="${! empty ERROR }">
<div class="alert alert-danger"><strong>${ERROR}!</strong></div>
</c:if>
자료올릴거니 폼 속성에
enctype="multipart/form-data" 넣고
클릭 후 이동은
"<c:url value="/DataRoom/Write.kosmo"/>"
등등 밑에 자바스크립트로 로직 처리하는 것도 추가!

<jsp:include page="/template/Top.jsp"/> 
    <div class="container" style="margin-top:65px;"> 
        <div class="jumbotron bg-warning">
            <h1>자료실 작성<small>자료 파일을 등록 하세요</small></h1>
        </div>
        <c:if test="${! empty ERROR }">
          <div class="alert alert-danger"><strong>${ERROR}!</strong></div>
       </c:if>
        <form method="post" enctype="multipart/form-data" action="<c:url value="/DataRoom/Write.kosmo"/>">
     		<div class="form-group">
	       		 <label><kbd class="lead">올린이</kbd></label>
	        	<input type="text" class="form-control" placeholder="이름을 입력하세요" name="name" value="${empty param.name? "" :param.name }">
	      	</div>     	
	     	<div class="form-group">
	        	<label><kbd class="lead">제목</kbd></label>
	        	<input type="text" class="form-control" placeholder="제목을 입력하세요" name="title" value="${empty param.title? "" :param.title }" >
	      	</div>
	      	<div class="form-group">
	        	<label><kbd class="lead">자료 파일</kbd></label>
	        	<input type="file" class="form-control-file" multiple name="attachFile">${empty param.attachFile? "" :param.attachFile }
	      	</div>
	      	<div class="form-group">
	        	<label><kbd class="lead">비밀번호</kbd></label>
	        	<input type="password" class="form-control" name="password" placeholder="비밀번호를 입력하세요">
	      	</div>
	      	<div class="form-group">
			<label><kbd class="lead">내용</kbd></label>
				<textarea class="form-control" rows="5" name="content">${empty param.content? "" :param.content}</textarea>
		  	</div>
      		<button type="submit" class="btn btn-primary">등록</button>
   		</form>  	
      	
    </div>
<jsp:include page="/template/Footer.jsp"/> 
 <script>
    /*
    //[0]은 첫번째 파일 의미
	//파일 사이즈(바이트):파일객체(자스 DOM).files[0].size
	//파일 명:파일객체(자스 DOM).files[0].name
	//파일 컨텐츠 타입:파일객체(자스 DOM).files[0].type      
    */
    var attaches = document.querySelector("input[type=file]");
    var form = document.querySelector("form[enctype='multipart/form-data']");
     form.onsubmit=function(){
    	 console.log(attaches.files);
    	 for(var i=0 ; i<attaches.files.length ;i++){
    		 console.log('파일명:%s,크기:%s,컨텐츠 타입:%s',attaches.files[i].name,attaches.files[i].size,attaches.files[i].type);    	
	    	 if(attaches.files[i].size > 1024*500 ){
	    		 alert("용량 초과")
	    		 return false;
	    	 }	 
    	 } 	
     };    
    
   </script>




list목록에서 파일 글자를 클릭하면 파일을 다운로드하게 만들것
그럼 따로 jsp파일은 없어도 되고 대신 컨트롤러만 필요 하겠다
DownloadController.java

@WebServlet("/DataRoom/Download.kosmo")
public class DownloadController extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String no = req.getParameter("no");
		String filename = req.getParameter("filename");
		//1.다운로드 관련된 모델 호출
		//2.파일다운로드 로직 호출
		FileUtils.download(filename,"/upload", req, resp);
		//3.테이블의 다운로드 수 컬럼 증가용 데이터베이스 관련 로직
		DataRoomDAO dao=new DataRoomDAO(getServletContext());
		dao.updateDawnCount(no);
		dao.close();
	}
}


이렇게 되면 fileuitls에 다운로드 로직이랑
dao 에 커럼수 증가용 로직을 만들어야 겠네...

다운로드 로직
public static void download(String filename,String webPath,HttpServletRequest request,HttpServletResponse response) {
    try {
        String saveDirectory = request.getServletContext().getRealPath(webPath);		
        File file = new File(saveDirectory+File.separator+filename);
        long length = file.length();
        response.setContentType("application/octect-stream");
        response.setContentLengthLong(length);
        boolean isIe = request.getHeader("user-agent").toUpperCase().indexOf("MSIE") != -1 ||
                       request.getHeader("user-agent").toUpperCase().indexOf("11.0") != -1 ||
                       request.getHeader("user-agent").toUpperCase().indexOf("EDGE") != -1 ;
        if(isIe) {//인터넷 익스플로러 혹은 엣지
            filename = URLEncoder.encode(filename,"UTF-8");
        }
        else {
            filename = new String(filename.getBytes("UTF-8"),"8859_1");
        }

        response.setHeader("Content-Disposition", "attachment;filename="+filename);

        BufferedInputStream bis =
                new BufferedInputStream(new FileInputStream(file));
        BufferedOutputStream bos=
                new BufferedOutputStream(response.getOutputStream());
        int data;
        while((data=bis.read())!=-1){
             bos.write(data);
             bos.flush();					
        }
            bis.close();
            bos.close();
      }
      catch(Exception e) {e.printStackTrace();}								
}

Dao로 가서 다운로드 수 증가용 메소드 추가

public void updateDawnCount(String no) {
    String sql="UPDATE dataroom SET downcount=downcount+1 WHERE no=?";
    try {
        psmt = conn.prepareStatement(sql);
        psmt.setString(1, no);
        psmt.executeUpdate();
    }
    catch(SQLException e) {e.printStackTrace();}
}

list에 다운로드 수 적용 시키기

<tbody class="table-sm down-file-body">
    <c:if test="${empty records}" var="isEmpty">
    <tr>
        <td colspan="5">등록된 글이 없습니다.</td>
    </tr>
    </c:if>	
    <c:if test="${not isEmpty }">
        <c:forEach var="record" items="${records}" varStatus="loop">
            <tr>
                <td>${record.no}</td>	
                <td class="text-left"><a href='<c:url value="/DataRoom/View.kosmo?no=${record.no}"/>'>${record.title}</a></td>
                <td>${record.name }</td>	
                <td>
                <ul class="list-unstyled">
                <c:forEach var="file" items="${fn:split(record.attachFile,',')}">
                    <li><a class ="down-file${loop.count}" href="<c:url value="/DataRoom/DownLoad.kosmo?filename=${file}&no=${record.no}"/>">${file}</a></li>
                </c:forEach>
                </ul>
                </td>	
                <td id="down-count${loop.count}">${record.downCount}</td>
                <td>${record.postDate}</td>				
            </tr>
        </c:forEach>
    </c:if>			
</tbody>

list 밑에 자바스크립트로 다운로드 수 관련 로직 작성

 <script>
  
   var tbody = document.querySelector(".down-file-body");
   tbody.onclick=function(e){
	   console.log(e.target.nodeName);
	   if(e.target.nodeName ==='A'){
		   console.log('클릭한 A태그의 클래스명:',e.target.className);
		   //a태그의 클래스명에서 끝에 숫자 추출
		   var className = e.target.className;
		   var numbering = className.substring("down-file".length,className.length);
		   console.log("넘버링 숫자:",numbering);
		   //아이디로 다운수가 있는  td요소 얻기
		   var td=tbody.querySelector("#down-count"+numbering);	   
		 //다운수 읽어오기(숫자로 변환)
		   var downCount= parseInt(td.textContent);
		 //1을 더해서 다시 설정
		td.textContent=downCount+1;   
	   }
   };
  
  </script>

+ Recent posts