이번 팀프로젝트중 CKEditor를 추가해보았습니다.

 

기본 설정은 이전에 작성한 포스팅을 참고 부탁드립니다.

https://nam-00.tistory.com/60

 

CKEditor5 사용해보기 1

1. CKEditor 사용 준비하기CKEditor CDN 설정 및 import 설정 CKEditorConfig.js 만들기import { AccessibilityHelp, Autoformat, AutoImage, Autosave, BlockQuote, Bold, CloudServices, Essentials, Heading, ImageBlock, ImageInline, ImageInsert, ImageI

nam-00.tistory.com

 

Controller Code(CKEditor를 사용하기 위해 생성한 클래스 및 필터

Mkdir_File.java (폴더 생성 클래스)

package controller.function;

import java.io.File;

public class Mkdir_File {
	public static void create(String folder_path) {
		
		// File 객체 생성
		File folder = new File(folder_path);

		// 폴더가 존재하는지 확인하고, 없으면 생성
		if (!folder.exists()) {
			boolean flag = folder.mkdirs();  // 폴더를 생성

			if (flag) {
				System.out.println("폴더 생성 완료 : " + folder_path);
			} 
			else {
				System.out.println("폴더 생성 실패");
			}
		} 
		else {
			System.out.println("폴더가 존재 : " + folder_path);
		}
		System.out.println("파일 생성 종료");
	}
	
	
}

 

CKEditorDeleteFile.java (최종 이미지와 서버에 저장된 파일 확인 클래스)

package controller.function;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;

public class CKEditorDeleteFile {

	public static void imgDelete(String content, String uploadPath) {
		//----------------------------------------------------------------------------
		//파일이 있는지 확인하기 위해 해당 폴더의 파일을 가져옵니다.
		File directory = new File(uploadPath);
		//폴더에 있는 파일리스트를 가져옵니다.

		//배열리스트로 전환
		ArrayList<File> arr_files = new ArrayList<File>(Arrays.asList(directory.listFiles()));

		//보내준 파일에서 이미지 경로만 문자열 배열로 불러와 줍니다.
		String[] img_paths = content.split("src=\"");

		//문자열 배열을 기준으로 for문을 돌립니다.
		for(String img_path : img_paths) {
			System.out.println("받아온 이미지 태그 : "+img_path);
			try {
				//저장된 주소+받아온 이미지 경로 끝에 큰따옴표(")가 붙어있기 때문에 제거해줍니다.
				String editorContent = uploadPath+File.separator+img_path.split("\"")[0].toString().substring(img_path.split("\"")[0].lastIndexOf("/")+1);
				//받은 이미지 로그
				System.out.println("이미지 : "+editorContent);
				File remove_file = new File(editorContent);
				//만약 파일이 있다면 배열에서 삭제합니다.
				if(arr_files.remove(remove_file)) {
					System.out.println("배열리스트에서 지워진 이미지 : " + remove_file);
				}
			}catch (Exception e) {

			}
		}

		//forEach 를 사용하여 배열을 확인하고
		for (File file : arr_files) {
			//삭제 파일 로그
			System.out.println("삭제된 파일 : "+file);
			//해당 파일을 삭제합니다.
			file.delete();
		}
		//----------------------------------------------------------------------------
	}
}

 

CKEditor_Upload.java (이미지 업로드를 위한 비동기 Servlet)

package controller.asycnServlet;

import java.io.File;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

import controller.function.LoginCheck;
import controller.function.Mkdir_File;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.Part;

@WebServlet("/ckupload")
@MultipartConfig
public class CKEditor_Upload extends HttpServlet {
	private static final long serialVersionUID = 1L;

    public CKEditor_Upload() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//--------------------------------------------------------------------------
		//FIXME 사용된 변수명

		//세션을 불러와서
		HttpSession session = request.getSession();
		
		//로그인 정보가 있는지 확인해주고
		String login[] = LoginCheck.Success(request, response);
		String member_id = login[0];//세션에 있는 사용자의 아이디
		
        response.setContentType("application/json");
        // simpleUpload 의 기본 파라미터는 "upload" 파라미터로 전송된다.
        Part filePart = request.getPart("upload"); 
        //넘어오는 파일의 명칭과 형식을 가져와서 변수에 저장합니다.
        String fileName = filePart.getSubmittedFileName();
        //받아온 파일의 형식만 불러와줍니다.
        String fileform = fileName.substring(fileName.lastIndexOf("."));
        
		//이미지이름을 보안코드로 변환하여 서버에 저장해줍니다.
		fileName = CKEditor_Upload.img_security()+fileform;
        
        //저장할 폴더 명칭
        String folerName = "/board_img/"+member_id+"/";
        //가져온 파일을 저장할 위치를 지정해줍니다.
        String uploadPath = getServletContext().getRealPath(folerName);
        //저장될 위치를 확인하기 위한 로그
        System.out.println("파일 주소 : "+uploadPath);
		
		//세션에 저장되어 있는 폴더 개수를 가져옵니다. 삼항연산자로 만약 세션값이 null이 아니라면 정수형으로 변경하여 가져오도록 수정
		int folder_session = (session.getAttribute("FOLDER_NUM") != null) ? (Integer)session.getAttribute("FOLDER_NUM"):0;
		System.out.println(session.getAttribute("UPDATE_FOLDER_NUM"));
		//세션에 저장되어 있는 폴더 개수를 가져옵니다. 삼항연산자로 만약 세션값이 null이 아니라면 정수형으로 변경하여 가져오도록 수정
		int update_folder_session = (session.getAttribute("UPDATE_FOLDER_NUM") != null) ? (Integer)session.getAttribute("UPDATE_FOLDER_NUM"):0;
		
		//--------------------------------------------------------------------------
		//FIXME 저장될 폴더를 생성 로직
		int folder_num = 0;
		//폴더가 없을 수 있기 때문에 만들어둔 폴더생성 함수를 활용
		Mkdir_File.create(uploadPath);
		if(update_folder_session > 0) {
			System.out.println("CKEditor_Upload.java folder_session 로그 : "+update_folder_session);
			folder_num = update_folder_session;
		}
		else {
			//현재 폴더 개수를 불러와줍니다.
			//(처음 불러올때는 서버/사용자폴더/ 로 불러옵니다)
			folder_num = CKEditor_Upload.member_folder_num(uploadPath);
			//만약 저장되어 있는 개수가 없다면
			if(folder_session <= 0 && update_folder_session <= 0) {
				//사용자의 게시판 이미지 폴더 개수 확인용 로그
				System.out.println("사용자 게시판 이미지 폴더 확인용 로그 :"+folder_num);
				//번호를 불러와서 +1을 해준다음
				folder_num = CKEditor_Upload.member_folder_num(uploadPath)+1;
				//폴더를 추가해줍니다.
				Mkdir_File.create(uploadPath+folder_num);
				//추가된 폴더의 번호를 세션에 저장해줍니다.
				session.setAttribute("FOLDER_NUM", folder_num);
			}
		}
		//--------------------------------------------------------------------------
		//FIXME 서버에 이미지 파일 저장 로직
		//파일 주소가 변경되었으니 변경된 주소를 추가해줍니다.
		uploadPath = uploadPath + "/" + folder_num;
			
		
		//받아온 주소로 파일을 저장합니다.
        //운영체제마다 파일 구분자가 다르기 때문에 File.separator를 추가해줍니다.
		//이런 File.separator 클래스가 있다는 걸 처음보아 사용해보았습니다.
        filePart.write(uploadPath + File.separator + fileName);
        
		//--------------------------------------------------------------------------
		//FIXME View로 서버에 저장된 주소를 전달하는 로직
        //view로 보내줄 파일 주소를 저장해서 전달해줍니다.
        String fileUrl = request.getContextPath() + folerName + folder_num + "/" + fileName;
        System.out.println("파일 주소 : "+fileUrl);
        response.getWriter().write("{ \"url\": \"" + fileUrl + "\" }");
     	//--------------------------------------------------------------------------
	}
	
	//현재 폴더 개수를 가져오는 함수 
	private static int member_folder_num(String uploadPath) {
		//폴더 위치를 불러옵니다.
		File directory = new File(uploadPath);
		//폴더에 있는 파일리스트를 가져오고 배열리스트로 전환합니다.
		ArrayList<File> arr_files = new ArrayList<File>(Arrays.asList(directory.listFiles()));
		System.out.println(arr_files);
		//해당 폴더의 개수를 반환해줍니다.
		return arr_files.size();
	}
	
	private static String img_security() {
		String security_code = "";
		try {
		//랜덤한 보안키를 만들기 위한 Random 함수를 추가
		Random rnd = new Random();

		//랜덤한 숫자를 받아오고
		String rndKey = Integer.toString(rnd.nextInt(32000));
		//랜덤 숫자를 변환할 형식을 지정해줍니다.
		MessageDigest md = MessageDigest.getInstance("MD5");
		
		//랜덤 숫자를 바이트 형식으로 변환하고
		byte[] bytData = rndKey.getBytes();
		//"MD5" 형식으로 변환합니다.
		md.update(bytData);
		//랜덤 숫자로 만들어야 하므로 변환한 형식을 바이트로 만들어주고
		byte[] digest = md.digest();
		for(int i =0;i<digest.length;i++){
			//변환된 형식의 보안 코드를 생성해줍니다.
			security_code = security_code + Integer.toHexString(digest[i] & 0xFF);
		}
		//해당 보안코드를 모두 사용하게 되면 너무 길기 때문에 11자리 숫자만 사용합니다.
		security_code = security_code.substring(0,11);
		
		} catch (NoSuchAlgorithmException e) {
			System.out.println("CKEditor_Upload.java 로그 MessageDigest.getInstance(\"MD5\") 생성오류 발생");
		}
		//보안코드를 반환해줍니다.
		return security_code;
	}
}

 

ValidFilter.java (이미지 수정을 위한 폴더 번호를 확인하기 위한 Filter)

package controller.common;

import java.io.IOException;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpFilter;
import jakarta.servlet.http.HttpServletRequest;

@WebFilter("*.do")
public class ValidFilter extends HttpFilter implements Filter {
       
    public ValidFilter() {
        super();
    }

	public void destroy() {
		System.out.println("로그 : 필터 종료");
	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest httpRequest = (HttpServletRequest)request;
		String uri=httpRequest.getRequestURI();
		String cp=httpRequest.getContextPath();
		String command=uri.substring(cp.length());
		System.out.println("command : "+command);
		
		if(command.equals("/BOARDUPDATEPAGEACTION.do")) {
			System.out.println("필터 UPDATE_FOLDER_NUM : "+httpRequest.getSession().getAttribute("UPDATE_FOLDER_NUM"));
		}
		else if(command.equals("/BOARDUPDATEACTION.do")){
			System.out.println("필터 UPDATE_FOLDER_NUM : "+httpRequest.getSession().getAttribute("UPDATE_FOLDER_NUM"));			
		}
		else {
			if(httpRequest.getSession().getAttribute("UPDATE_FOLDER_NUM") != null) {
				httpRequest.getSession().setAttribute("UPDATE_FOLDER_NUM", "");
			}
		}
		
		chain.doFilter(request, response); 
	}
	
	public void init(FilterConfig fConfig) throws ServletException {
		System.out.println("로그 : 필터 시작");
	}

}

 

기본적으로 사용할 이미지 업로드하기 위한 코드를 설정해주었습니다.

이후 작성할 코드들은 글이 작성될때 사용자 아이디와

그 사용자의 게시판 이미지 폴더를 생성해 저장하는 코드

 

글이 수정될때 게시판 이미지 폴더에 이미지를 수정하는 코드를 작성하겠습니다.

728x90
개발자가 되고 싶은 곰