카테고리 없음

0311 오전수업

unemo 2021. 3. 11. 12:48
반응형
@RequestMapping("/detail")

getpds할때조회수 올릴거냐말거냐

파일명을 원본파일명으로

@RequestMapping("/detail")
	public ModelAndView detail(int pno, ModelAndView mnv, String from) throws Exception{
		String url = "pds/detail.open";
		
		
		PdsVO pds = null;
		
		//디테일은 두가지상황에서열림 실제상세보기, 수정한 다음 구분해야함
		if(from!=null && from.equals("modify")) {
			pds=pdsService.getPdsForModify(pno);
		}else {
			pds=pdsService.getPds(pno);
//			replyList = replyService.getReplyList(bno, cri);
		}
		
		List<AttachVO> attachList = pds.getAttachList();
		if(attachList != null) {
			for(AttachVO attach : attachList) {
				String fileName = attach.getFileName().split("\\$\\$")[1];
				attach.setFileName(fileName);
			}
		}
		
		mnv.addObject("pds",pds);
		mnv.setViewName(url);
		
		return mnv;
	}
	@RequestMapping("/registForm")
	public ModelAndView registForm(ModelAndView mnv) throws Exception{
		String url = "pds/regist.open";
		mnv.setViewName(url);
		return mnv;
	}
@RequestMapping("/modifyForm")
	public ModelAndView modifyForm(ModelAndView mnv, int pno) throws Exception{
		String url = "pds/modify.open";
		PdsVO pds = pdsService.getPdsForModify(pno);
		
		//파일정재정의
		List<AttachVO> attachList = pds.getAttachList();
		if(attachList!=null) {
			for(AttachVO attach : attachList) {
				String fileName = attach.getFileName().split("\\$\\$")[1];
				attach.setFileName(fileName);
			}
		}
		mnv.addObject("pds",pds);
		mnv.setViewName(url);
	
		return mnv;
	}

첨부파일의 파일명 수정해줘야한다는것고려하기

 

모디파이폼이 더 할일은 많지만(삭제되는파일도 받아야하니까) 파일처리를 해야한다는 점에서 레지스트랑 겹친다

 

attachvo 는 해당파일에대한 정보들을 스트링타잉ㅂ으로 저장하는거기떄문에 멀티파일로 받을수없다

pdsVO에서 저 List<attachVO>가 아니라 MultipartFile[]을 받아야함 (파일이 넘어오니까)

그래서 중간에 낄 커맨드 객체로 한번에 받으려고 하는거임

 

커맨드객체에 pno는 없을거임 db에 들어갈떄 만들어지니까 ( viewcnt,updatdate,regdate도 없음 사용자가 넘겨주는 데이터를 기준으로 ㅁ만드는거기떄문에)

 

커맨드객체를 받는 주목적은 데이터를 인계하는거에 의미가있음

 

예전에 파일업로드리졸버 만들엇던시절에. 커먼업로드자르로 아이템즈를 받앗엇음. 아이템리스트받아서 파일업ㄹ로드리졸버가 그 아잍메리스트들을 하나씩꺼내면서 isnotfield로 필드가 아닌것만 어태치브이오에 저장햇엇음

근데 스프링오면서 멀티파트파일을 바로받을수잇으니까 노란작업 할필요없고 (파서필요없)커맨드로 바로 멀티파트 받아서 파일업로드리졸버 따로만들지않고 savefile()메서드만들어서 아이템즈 대신 멀티파트파일배열을 받아서 처리하면됨

 

면접질문 : 스프링mvc어케적용햇는지, 머가어려웠는지 db구축시 이슈, 


커맨드객체는 화면이 그려져야함 (이미 화면설꼐 끝났을거기떄문에 그려질거임)

 

package kr.or.ddit.command;

import java.util.List;

import org.springframework.web.multipart.MultipartFile;

public class PdsRegistCommand {

	//궁극적인 타겟은 셋메서드이기떄문에 셋을 뺴고 메서드명이 파라미터랑동일해야함
	private String title;
	private String content;
	private String writer;
	private List<MultipartFile> uploadFile;
	
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public List<MultipartFile> getUploadFile() {
		return uploadFile;
	}
	public void setUploadFile(List<MultipartFile> uploadFile) {
		this.uploadFile = uploadFile;
	}
	
	
}

 

이게 서비스에 넘기는 pdsVO만들기위해서 파라미터받는거임

	public PdsVO toPdsVO() {
		PdsVO pds = new PdsVO();
		pds.setContent(this.content);
		pds.setTitle(this.title);
		pds.setWriter(this.writer);
		
		return pds;
	}
//attachVO는 저장을 해야 나오고, pno는 만들어서들어가니까..
}

 

regist 시그니처를 만들어보자

리스펀스아웃으로 뭔가날리는구나 추측가능

파일저장경로는 빈등록된걸로 가져오면됨 

이걸처리하는과정에서 script로 로케이션href날릴려고하는데

로케이션href는 브라우저에서 실행하는 명령문이라 contextpath필요함 그래서 request받은거임

파일이 넘어올떄 파라미터명을 상관없ㅇ는데 파일명이 헤더에잡혀옴.. 주소줄도 아니고 리퀘스트바디에잇는것도아닉떄문에 ㅂ한글이꺠지는 문제가생김. 그걸떄지지않게하기위해서 

이거준거임

 

 

저장해야하니까 저장경로설정

 

 

v파일파라미터 받고 저장하는 부분이

여기

	private List<AttachVO> saveFile(PdsRegistCommand registReq) throws Exception{
		String fileUploadPath = this.fileUploadPath;
		
		List<AttachVO> attachList = new ArrayList<AttachVO>();
		
		if(registReq.getUploadFile() != null) {
			for(MultipartFile multi : registReq.getUploadFile()) {
				String fileName = UUID.randomUUID().toString().replace("-", "")+
						"$$" + multi.getOriginalFilename();
				File target = new File(fileUploadPath,fileName);
				
				if(!target.exists()) {
					target.mkdirs();
				}
				
				multi.transferTo(target);
				
				AttachVO attach = new AttachVO();
				attach.setUploadPath(fileUploadPath);
				attach.setFileName(fileName);
				attach.setFileType(fileName.substring(fileName.lastIndexOf(".")+1).toUpperCase());
			
				attachList.add(attach);
				
			}
		}
		return attachList;
	}

 

	@RequestMapping(value = "/regist", method = RequestMethod.POST, 
					produces = "text/plain;charset=utf-8")
	public void regist(PdsRegistCommand registReq,
					   HttpServletRequest request,HttpServletResponse response)
			throws Exception {
		List<AttachVO> attachList = saveFile(registReq);
		
		PdsVO pds = registReq.toPdsVO();
		pds.setAttachList(attachList);
		
		service.regist(pds);
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println("<script>");
		out.println("alert('정상적으로 등록되었습니다.');");
		out.println("window.opener.location.href='"+request.getContextPath()+"/pds/list';");
		out.println("window.close();");
		out.println("</script>");
		
	}

스크립트로 화면 리다이렉트하기때문에

리퀘스트가 갱신되어서 model이 필요가없다.                                                                    

 

 

 

모디파이에서는 세이브파일이용할건데 파일삭제도해야하므로 커맨드 하나더만들어야함

레지스트랑 차이점이 pno 받아야하고 delete파일에 대한 정보를 받아야함

레지스트커맨드를 상속받고 추가만해서만들거임

package kr.or.ddit.command;

import kr.or.ddit.dto.PdsVO;

public class PdsModiftCommand extends PdsRegistCommand {
	
	private int pno;
	private int[] deleteFile;
	public int getPno() {
		return pno;
	}
	public void setPno(int pno) {
		this.pno = pno;
	}
	public int[] getDeleteFile() {
		return deleteFile;
	}
	public void setDeleteFile(int[] deleteFile) {
		this.deleteFile = deleteFile;
	}
	
	
	@Override
	public PdsVO toPdsVO() {
		PdsVO pds = super.toPdsVO();
		pds.setPno(this.pno);
		
		return pds;
	}
}

 

매서드시그니처는 이제 커맨드가 바뀜 (모디파이커맨드로)

 

삭제될파일이있따면 먼저 삭제를 하자

모디파이리퀘스트의 딜리트파일이있는상태에서Mapping("/detail")

getpds할때조회수 올릴거냐말거냐

 

파일명을 원본파일명으로

 

@RequestMapping("/detail")

 public ModelAndView detail(int pno, ModelAndView mnv, String from) throws Exception{

  String url = "pds/detail.open";

  

  

  PdsVO pds = null;

  

  //디테일은 두가지상황에서열림 실제상세보기, 수정한 다음 구분해야함

  if(from!=null && from.equals("modify")) {

   pds=pdsService.getPdsForModify(pno);

  }else {

   pds=pdsService.getPds(pno);

// replyList = replyService.getReplyList(bno, cri);

  }

  

  List<AttachVO> attachList = pds.getAttachList();

  if(attachList != null) {

   for(AttachVO attach : attachList) {

    String fileName = attach.getFileName().split("\\$\\$")[1];

    attach.setFileName(fileName);

   }

  }

  

  mnv.addObject("pds",pds);

  mnv.setViewName(url);

  

  return mnv;

 }

 @RequestMapping("/registForm")

 public ModelAndView registForm(ModelAndView mnv) throws Exception{

  String url = "pds/regist.open";

  mnv.setViewName(url);

  return mnv;

 }

@RequestMapping("/modifyForm")

 public ModelAndView modifyForm(ModelAndView mnv, int pno) throws Exception{

  String url = "pds/modify.open";

  PdsVO pds = pdsService.getPdsForModify(pno);

  

  //파일정재정의

  List<AttachVO> attachList = pds.getAttachList();

  if(attachList!=null) {

   for(AttachVO attach : attachList) {

    String fileName = attach.getFileName().split("\\$\\$")[1];

    attach.setFileName(fileName);

   }

  }

  mnv.addObject("pds",pds);

  mnv.setViewName(url);

 

  return mnv;

 }

첨부파일의 파일명 수정해줘야한다는것고려하기

 

 

 

모디파이폼이 더 할일은 많지만(삭제되는파일도 받아야하니까) 파일처리를 해야한다는 점에서 레지스트랑 겹친다

 

 

 

attachvo 는 해당파일에대한 정보들을 스트링타잉ㅂ으로 저장하는거기떄문에 멀티파일로 받을수없다

pdsVO에서 저 List<attachVO>가 아니라 MultipartFile[]을 받아야함 (파일이 넘어오니까)

 

그래서 중간에 낄 커맨드 객체로 한번에 받으려고 하는거임

 

 

 

커맨드객체에 pno는 없을거임 db에 들어갈떄 만들어지니까 ( viewcnt,updatdate,regdate도 없음 사용자가 넘겨주는 데이터를 기준으로 ㅁ만드는거기떄문에)

 

 

 

커맨드객체를 받는 주목적은 데이터를 인계하는거에 의미가있음

 

 

 

예전에 파일업로드리졸버 만들엇던시절에. 커먼업로드자르로 아이템즈를 받앗엇음. 아이템리스트받아서 파일업ㄹ로드리졸버가 그 아잍메리스트들을 하나씩꺼내면서 isnotfield로 필드가 아닌것만 어태치브이오에 저장햇엇음

 

근데 스프링오면서 멀티파트파일을 바로받을수잇으니까 노란작업 할필요없고 (파서필요없)커맨드로 바로 멀티파트 받아서 파일업로드리졸버 따로만들지않고 savefile()메서드만들어서 아이템즈 대신 멀티파트파일배열을 받아서 처리하면됨

 

 

 

면접질문 : 스프링mvc어케적용햇는지, 머가어려웠는지 db구축시 이슈, 

 

커맨드객체는 화면이 그려져야함 (이미 화면설꼐 끝났을거기떄문에 그려질거임)

 

 

 

package kr.or.ddit.command;

 

import java.util.List;

 

import org.springframework.web.multipart.MultipartFile;

 

public class PdsRegistCommand {

 

 //궁극적인 타겟은 셋메서드이기떄문에 셋을 뺴고 메서드명이 파라미터랑동일해야함

 private String title;

 private String content;

 private String writer;

 private List<MultipartFile> uploadFile;

 

 public String getTitle() {

  return title;

 }

 public void setTitle(String title) {

  this.title = title;

 }

 public String getContent() {

  return content;

 }

 public void setContent(String content) {

  this.content = content;

 }

 public String getWriter() {

  return writer;

 }

 public void setWriter(String writer) {

  this.writer = writer;

 }

 public List<MultipartFile> getUploadFile() {

  return uploadFile;

 }

 public void setUploadFile(List<MultipartFile> uploadFile) {

  this.uploadFile = uploadFile;

 }

 

 

}

 

 

이게 서비스에 넘기는 pdsVO만들기위해서 파라미터받는거임

 

 public PdsVO toPdsVO() {

  PdsVO pds = new PdsVO();

  pds.setContent(this.content);

  pds.setTitle(this.title);

  pds.setWriter(this.writer);

  

  return pds;

 }

//attachVO는 저장을 해야 나오고, pno는 만들어서들어가니까..

}

 

 

regist 시그니처를 만들어보자

 

리스펀스아웃으로 뭔가날리는구나 추측가능

 

파일저장경로는 빈등록된걸로 가져오면됨 

 

이걸처리하는과정에서 script로 로케이션href날릴려고하는데

 

로케이션href는 브라우저에서 실행하는 명령문이라 contextpath필요함 그래서 request받은거임

 

파일이 넘어올떄 파라미터명을 상관없ㅇ는데 파일명이 헤더에잡혀옴.. 주소줄도 아니고 리퀘스트바디에잇는것도아닉떄문에 ㅂ한글이꺠지는 문제가생김. 그걸떄지지않게하기위해서 

 

이거준거임

 

 

 

 

저장해야하니까 저장경로설정

 

 

 

 

 

v파일파라미터 받고 저장하는 부분이

 

여기

 private List<AttachVO> saveFile(PdsRegistCommand registReq) throws Exception{

  String fileUploadPath = this.fileUploadPath;

  

  List<AttachVO> attachList = new ArrayList<AttachVO>();

  

  if(registReq.getUploadFile() != null) {

   for(MultipartFile multi : registReq.getUploadFile()) {

    String fileName = UUID.randomUUID().toString().replace("-", "")+

      "$$" + multi.getOriginalFilename();

    File target = new File(fileUploadPath,fileName);

    

    if(!target.exists()) {

     target.mkdirs();

    }

    

    multi.transferTo(target);

    

    AttachVO attach = new AttachVO();

    attach.setUploadPath(fileUploadPath);

    attach.setFileName(fileName);

    attach.setFileType(fileName.substring(fileName.lastIndexOf(".")+1).toUpperCase());

   

    attachList.add(attach);

    

   }

  }

  return attachList;

 }

 

 

 @RequestMapping(value = "/regist", method = RequestMethod.POST, 

     produces = "text/plain;charset=utf-8")

 public void regist(PdsRegistCommand registReq,

        HttpServletRequest request,HttpServletResponse response)

   throws Exception {

  List<AttachVO> attachList = saveFile(registReq);

  

  PdsVO pds = registReq.toPdsVO();

  pds.setAttachList(attachList);

  

  service.regist(pds);

  response.setContentType("text/html;charset=utf-8");

  PrintWriter out = response.getWriter();

  out.println("<script>");

  out.println("alert('정상적으로 등록되었습니다.');");

  out.println("window.opener.location.href='"+request.getContextPath()+"/pds/list';");

  out.println("window.close();");

  out.println("</script>");

  

 }

스크립트로 화면 리다이렉트하기때문에

 

리퀘스트가 갱신되어서 model이 필요가없다.                                                                    

 

 

 

 

 

 

 

모디파이에서는 세이브파일이용할건데 파일삭제도해야하므로 커맨드 하나더만들어야함

 

레지스트랑 차이점이 pno 받아야하고 delete파일에 대한 정보를 받아야함

 

레지스트커맨드를 상속받고 추가만해서만들거임

 

package kr.or.ddit.command;

 

import kr.or.ddit.dto.PdsVO;

 

public class PdsModiftCommand extends PdsRegistCommand {

 

 private int pno;

 private int[] deleteFile;

 public int getPno() {

  return pno;

 }

 public void setPno(int pno) {

  this.pno = pno;

 }

 public int[] getDeleteFile() {

  return deleteFile;

 }

 public void setDeleteFile(int[] deleteFile) {

  this.deleteFile = deleteFile;

 }

 

 

 @Override

 public PdsVO toPdsVO() {

  PdsVO pds = super.toPdsVO();

  pds.setPno(this.pno);

  

  return pds;

 }

}

 

 

매서드시그니처는 이제 커맨드가 바뀜 (모디파이커맨드로)

 

 

 

삭제될파일이있따면 먼저 삭제를 하자

 

모디파이리퀘스트의 딜리트파일이있는상태에서

 

 pno지우기전에 파일삭제먼저해야됨

pno가지고 어태치에 조회해서 파일정보 가지고 와서파일을 지움 그 후에! pds날려도 늦지않다

	@RequestMapping(value = "modify", method = RequestMethod.POST)
	public void modifyPOST(PdsModifyCommand modifyReq, HttpServletRequest request, HttpServletResponse response) throws Exception{
		//삭제된파일삭제
		if(modifyReq.getDeleteFile() !=null && modifyReq.getDeleteFile().length > 0) {
			for (int ano : modifyReq.getDeleteFile()) {
				AttachVO attach = attachDAO.selectAttachByAno(ano);
				String fileName = attach.getFileName();
				File deleteFile  = new File(attach.getUploadPath(), fileName);
				
				//db삭제
				attachDAO.deleteAttach(ano);

				//file삭제
				if(deleteFile.exists()) {
					deleteFile.delete();
				}
			}
		}
		
		//추가 혹은 변경된 파일 저장
		List<AttachVO> attachList = saveFile(modifyReq);
		
		//PdsVO setting
		PdsVO pds = modifyReq.toPdsVO();
		pds.setAttachList(attachList);
		
		//DB에 해당 데이터 추가
		service.modify(pds);
		
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println("<script>");
		out.println("alert('수정되었습니다..');");
		out.println("location.href='detail?pno"+pds.getPno()+"&from=modify';");
		out.println("window.close();");
		out.println("</script>");
		
		out.close();
	}

 

 

지운후화면처리에 대한것때문에

response 사용하게됨

	@RequestMapping("/remove")
	public void remove(int pno, HttpServletResponse response) throws Exception{
		//첨부파일 삭제
		List<AttachVO> attachList = attachDAO.selectAttachesByPno(pno);
		if(attachList ! = null) {
			for(AttachVO attach : attachList) {
				File target = new File(attach.getUploadPath(), attach.getFileName());
				if(target.exists()) {
					target.delete();
				}
			}
		}
	}	

이제 디비삭제가 이루어지면서

pds, attachtable 에 잇는 데이터가 cascade로 같이 다 날라감

 

//DB삭제
		service.remove(pno);
		
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println("<script>");
		out.println("alert('삭제되었습니다..');");
		out.println("window.opener.location.reload(true);");
		out.println("window.close();");
		out.println("</script>");
		
		out.close();

 

자료실이니까

상세보기햇을떄 처부파일 나열될거고 눌럿을떄 다운로드

다운로드에대한 컨트롤러

파일선택하면 ano를 유알ㅇ로 던짐. attachvo가져와서 파일네임 가져와서 다운할수잇도록 파일네임내보냄

 

파일을 땡겨야함 > inputstream

 

 

uuid 없애고 헤더에 대한 세팅을 파일명으로 나갈수있게해주기

깨지지않게

 

가져올떄는 produces 내보낼떄는 인코딩 기억

@RequestMapping("/getFile")
	public ResponseEntity<byte[]> getFile(int ano) throws Exception{
		InputStream in = null;
		ResponseEntity<byte[]> entity = null;
		AttachVO attach = attachDAO.selectAttachByAno(ano);
		String fileUploadPath = this.fileUploadPath;
		String fileName = attach.getFileName();
	
		try {
			in = new FileInputStream(fileUploadPath + File.separator + fileName);
			
			fileName = fileName.substring(fileName.indexOf("$$")+2);
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
			headers.add("Content-Disposition","attachment;filename=\""+new String(fileName.getBytes("utf-8"),"ISO-8859-1")+"\"");
			
			entity = new ResponseEntity<byte[]>(IOUtils.toByteArray(in),headers,HttpStatus.CREATED);
		}catch(IOException e) {
			e.printStackTrace();
			entity = new ResponseEntity<byte[]>(HttpStatus.INTERNAL_SERVER_ERROR);
			
		}finally {
			if(in!=null)in.close();
		}
		
		return entity;
	}

 

 

 jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

    
    
<head>
<style>
	
	table th,td{
		text-align:center;		
	}
	
</style>
</head>


 <div class="content-wrapper" >
	
    <!-- Main content -->
    <section class="content">		
		<div class="card">
			<div class="card-header with-border">
				<button type="button" class="btn btn-primary" id="registBtn" onclick="OpenWindow('registForm.do','글등록',800,700);">글등록</button>				
				<div id="keyword" class="card-tools" style="width:350px;">
					<div class="input-group row">						
						<select class="form-control col-md-4" name="searchType" id="searchType">
										
						</select>					
						<input  class="form-control" type="text" name="keyword" placeholder="검색어를 입력하세요." value="${param.keyword }"/>
						<span class="input-group-append">
							<button class="btn btn-primary" type="button" onclick="searchList_go(1);" 
							data-card-widget="search">
								<i class="fa fa-fw fa-search"></i>
							</button>
						</span>
					</div>
				</div>						
			</div>
			<div class="card-body">
				<table class="table table-bordered text-center" >					
					<tr style="font-size:0.95em;">
						<th style="width:10%;">번 호</th>
						<th style="width:50%;">제 목</th>
						<th style="width:15%;">작성자</th>
						<th>등록일</th>
						<th style="width:10%;">조회수</th>
					</tr>				
					
					
				</table>				
			</div>
			<div class="card-footer">
			
			</div>
		</div>
		
    </section>
    <!-- /.content -->
  </div>
  <!-- /.content-wrapper -->	

 

여기 나오게 하기

제목길때 ...으로 표시하고싶다

등록

타일즈는 해당 jsp없으면 404가 아니고 500이 나옴

타일즈 리졸버가 .open 을 받앗는데 jsp없으면 500

그냥 view는 인터널이 받아서 jsp없으면 404

 

반응형