JSP

JSP_이미지_게시판

climb-up 2022. 5. 9. 21:34

보드 안에 여러개 파일이 들어가면
보드(부모) 파일(자식)fk외부키: boardId ->boardId가 pk로 들어갈 필요없음.

**사진저장 원리**
: 사진->DB에 저장한다면 ->사진에 대한 경로가 들어간다.
: 파일이 DB자체에 들어가는게 아니라 파일저장소의 경로(+파일이름)가 들어간다.
: 파일을 받으면 파일 저장소(서버/폴더)에 원본파일 복사가 이루어진다.
파일저장소에 변경된 이름으로 들어간다.

 

ex)
사진을 카톡으로 보내면 다른사람들도 다 다운받을 수 있다.
카톡에 사진보내고 내폰에 있는 이미지 지운경우 카톡방에 있는 사진을 다시 필요하면 다시 다운받는다.

 

<이미지 게시판 폼을 뷰로 전달한다>

@WebServlet("/writerThumForm.th")
public class WriterThumbForm extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public WriterThumbForm(){
    	super();
    }
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOEception {
    	request.getRequestDispatcher("WEB-INF/views/thumbnail/thumbnailWriteForm.jsp").forward(request, response);
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
}

 

<뷰에 보여줄 폼을 작성>

thumbnailWriteForm.jsp 작성

<form action="<%= request.getContextPath() %>/insert.th" method="post" edType="multipart/form-data">

encType = "multipart/form-data" : 파일을 보낼 때 필수적으로 인코딩 타입지정이 필요하다.

파일 전송을 위한 코드

 

<폼의 스트립트>

<script>
// 내용 작성 부분의 공간을 클릭할 때 파일 첨부 창이 뜨도록 설정하는 함수
		$(function(){
			$("#fileArea").hide();
						
			$("#titleImgArea").click(function(){
				$("#thumbnailImg1").click();
			});
			$("#contentImgArea1").click(function(){
				$("#thumbnailImg2").click();
			});
			$("#contentImgArea2").click(function(){
				$("#thumbnailImg3").click();
			});
			$("#contentImgArea3").click(function(){
				$("#thumbnailImg4").click();
			});
		});
					
// 각각의 영역에 파일을 첨부 했을 경우 미리 보기가 가능하도록 하는 함수
		function LoadImg(value, num){
			if(value.files && value.files[0]){//파일이 존재한다면 실행해라->여러개 선택해도 그중에 첫번째 사진만 들어간다.
				var reader = new FileReader();
							
				reader.onload = function(e){								
					switch(num){
					case 1: 
						$("#titleImg").attr("src", e.target.result);
						break;
					case 2:
						$("#contentImg1").attr("src", e.target.result);
						break;
					case 3: 
						$("#contentImg2").attr("src", e.target.result);//이미지에 대한 사진을 보여줌(경로X)
						break;
					case 4:
						$("#contentImg3").attr("src", e.target.result);
						break;
					}
				}
							
				reader.readAsDataURL(value.files[0]);//가장 앞에 있는 사진 경로 데이터url로 읽어준다.
			}
		}
	</script>

: 내용 작성 부분의 공간을 클릭할 때 파일 첨부 창이 뜨도록 설정하는 함수가 필요하다!

: 파일이 존재한다면 실행하라 -> 여러 개 선택해도 그 중 첫번째 사진만 들어간다.

 

<파일 이름을 오늘날짜시간으로 변경해서 가져오기>

package common;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.oreilly.servlet.multipart.FileRenamePolicy;

public class MyFileRenamePolicy implements FileRenamePolicy{

	@Override
    public File rename(File originFile) { //MyFileRenamePolicy를 오버라이딩 해준다. //implements
		long currentTime = System.currentTimeMillis();
        int ranNum = (int)(Math.random() * 10000);
        
        String name = originFile.getName();//파일 이름
        String ext = null;//확장자
        int dot = name.lastIndexOf(".");//가장 마지막에 있는 .에 대한 인덱스를 가지고 와라
        if(dot == -1) {
        	ext = "";
        } else {
        	ext = name.substring(dot);//.PNG라고 나온다.(확장자)
        }
        SimpleDateFormat sdf = new SimpleDateFoemat("yyyyMMddHHmmssSSS");
        String fileName = sdf.format(new Date(currentTime)) + ranNum + ext;
        
        File newFile = new File(originFile.getParent(), fileName);
        //파일이 만들어지면 바꿔준 이름으로 fileName만들어 줘서 그 상태로 return newFile에 저장
        
        return newFile;
    }
}

1. originFile.getName을 통해 파일 이름을 가져와서 name변수에 넣어준다.

2. name.lastIndexOf(".")를 통해 가져온 파일의 .에 대한 인덱스를 가지고 와서

인덱스 -1가 아니면, substring(.에 대한 인덱스)를 넣어서 파일 확장자를 가져온다.

3. new SimpleDateFormat()을 통해 오늘 날짜로 파일명을 설정한다.

4. 3번에서 담은 sdf를 .format(new Date(currentTime)) + ranNum + ext;를 fileName에 담아서 

파일이 생성 되는 동시에 바뀐 이름으로 fileName을 만들어줘서 그 상태가 바로 return newFile에 저장반환한다.

 

 

@WebServlet("/insert.th")
public class InsertThumbnailServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public InsertThumbnailServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		
//		String title = request.getParameter("title");
//		System.out.println(title);
//		encType="multipart/form-data" 인코딩지정때문에 getParameter("title"); title 값을 가져올 수 없다.
//		==> MultipartRequest 
		
		if(ServletFileUpload.isMultipartContent(request)) {// multipart/form-data로 전송되었는지 확인
			// MultipartRequest 객체 사용법
			// MultipartRequest multiRequest = new MultipartRequest(HttpServletRequest, 파일저장소 경로, 파일 최대 크기, 인코딩 타입, 파일 명 변환 규칙);
			//	파일 명 변환 규칙에 사용되는 기본 클래스 : DefaultFileRenamePolicy
			//	같은 이름의 파일이 존재하면 파일 명 뒤에 숫자 붙임 ex) aaa.png, aaa1.png, aaa2.png
		
			int maxSize = 1024*1024*10; //10Mbyte
			String root = request.getSession().getServletContext().getRealPath("/");// /:WebContent아래를 말하는것
			String savePath = root + "thumbnail_uploadFiles/";
			
			File f = new File(savePath);
			if(!f.exists()) {
				f.mkdirs();
			}
//			System.out.println(savePath); //C:\5_Servlet_workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp2\wtpwebapps\3_JSPServlet\thumbnail_uploadFiles/
			// cos.jar 라이브러리 필요
			MultipartRequest multiRequest = new MultipartRequest(request, savePath, maxSize, "UTF-8", new MyFileRenamePolicy());
			//따로 규약을 넣지 않으면  new DefaultFileRenamePolicy()를 가져와서 쓰면된다. import 확인해보면 cos.jar를 사용햇는지 알 수 있다 
			//파일저장소에 저장이 되는 것 이다.
			
			String title = multiRequest.getParameter("title");
			String content = multiRequest.getParameter("content");
			String writer = ((Member)request.getSession().getAttribute("loginUser")).getUserId();
			
			ArrayList<String> saveFiles = new ArrayList<String>(); //파일의 바뀐 이름을 저장할 ArrayList
			ArrayList<String> originFiles = new ArrayList<String>(); //파일의 원래 이름을 저장할 ArrayList
			
			Enumeration<String> files = multiRequest.getFileNames();// input type="file"의 name값 반환값 Enumaratioin
			while(files.hasMoreElements()) {
//				System.out.println(files.nextElement());//name속성값의 Parameter명 나옴 thumbnailImg4/thumbnailImg3/thumbnailImg2/thumbnailImg1
				String name = files.nextElement(); //전송 순서 역순
				
				if(multiRequest.getFilesystemName(name) != null) {
					saveFiles.add(multiRequest.getFilesystemName(name));//바뀐이름의 파일명
					originFiles.add(multiRequest.getOriginalFileName(name));//원래 이름의 파일명
				}
			}
			
			Board b = new Board();
			b.setBoardContent(content);
			b.setBoardTitle(title);
			b.setBoardWriter(writer);
			b.setBoardType(2);
			b.setCategory("10");//카테고리 인설트보드 그대로 활용할 것이다(쿼리) 임의로 10을 넣어줌
			
			ArrayList<Attachment> fileList = new ArrayList<>();
			for(int i = originFiles.size() -1; i >= 0; i--) {//파일이 역순이어서 for문도 역순으로 씀.
				Attachment a = new Attachment();
				a.setFilePath(savePath);
				a.setOriginName(originFiles.get(i));
				a.setChangeName(saveFiles.get(i));
				
				if(i == originFiles.size() -1) {//썸네일 /역순으로 들어오니까 -1을 해서 
					a.setFileLevel(0);
				} else {
					a.setFileLevel(1);
				}
				
				fileList.add(a);
			}
			
			int result = new BoardService().insertFile(b, fileList);
			
			if(result == fileList.size() +1) {//잘들어갔다는 전제하에 +1과 같다면 진행
				response.sendRedirect("list.th");
			}else {
				request.setAttribute("msg", "사진게시판 등록에 실패하였습니다.");
				request.getRequestDispatcher("WEB-INF/views/common/errorPage.jsp").forward(request, response);
			
				for(int i = 0; i < saveFiles.size(); i++) {
					File failFile = new File(savePath + saveFiles.get(i));
					failFile.delete();
				}
			}
			
		}
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

MultipartRequest multiRequest = new MultipartRequest(HttpServletRequest, 파일저장소 경로, 파일 최대 크기, 인코딩 타입, 파일 명 변환 규칙);
: 파일 명 변환 규칙에 사용되는 기본 클래스 : DefaultFileRenamePolicy
: 같은 이름의 파일이 존재하면 파일 명 뒤에 숫자 붙임 ex) aaa.png, aaa1.png, aaa2.png