참조 :
http://macaronics.net/index.php/m01/java/view/143
* Smart Editor, WYSIWYG Editor(위지윅 에디터, what you see is what you get)
- 사용자가 현재 화면에서 보고 있는 내용과 동일한 html code를 생성하는 에디터
- 네이버, 다음 에디터, CKEditor, SummerNote 등
* CKEditor
- Standard Package 다운로드
- 이미지 업로드를 위해서는 별도의 작업이 필요함
- 적용 예
* SummerNote
- 이미지를 텍스트 형식으로 저장함, 이미지 링크 방식의 업로드를 위해서는 별도의 작업이 필요함
- 적용 예
CKeditor 업로드 설정은 다음 4가지만 고려하면 된다.
1. CKEditor 에서 파일을 넘겨주는 이름이 upload 로 설정 되어 있다. 반드시 upload 로 설정
@RequestMapping(value="/ckeditorupload")
public void imageUpload(HttpServletRequest request, HttpServletResponse response,
@RequestParam MultipartFile upload ) throws Exception{
2. 물리적 실제 저장소 설정
1)
servlet-context.xml
<!-- 서버의 파일 저장 경로 설정 --> <beans:bean id="uploadPath" class="java.lang.String"> <beans:constructor-arg value="D:\dev\spring_simple_blog\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\upload" /> </beans:bean>
//파일 디렉토리 사용시 @Resource(name="uploadPath") private String uploadPath;
UploadFileUtils
ckeditor 전용 파일 업로드를 만들었다.
썸네일 주소를 반환하는 것이 아닌 실제 이미지지 주소 반환
/** * <pre> * 1. 패키지명 : net.macaronics.web.controller * 2. 타입명 : test2.java * 3. 작성일 : 2017. 10. 24. 오후 7:40:39 * 4. 저자 : 최준호 * * </pre> * */ package config.upload; import java.awt.image.BufferedImage; import java.io.File; import java.text.DecimalFormat; import java.util.Calendar; import java.util.UUID; import javax.imageio.ImageIO; import org.imgscalr.Scalr; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.FileCopyUtils; public class UploadFileUtils { private static final Logger logger = LoggerFactory.getLogger(UploadFileUtils.class); private static Integer WIDTH_SIZE = 100; public static Integer getWIDTH_SIZE() { return WIDTH_SIZE; } public static void setWIDTH_SIZE(Integer wIDTH_SIZE) { WIDTH_SIZE = wIDTH_SIZE; } // 1.파일의 저장 경로(uploadPath), 2.원본 파일의 이름(originalName), 3.파일 데이터(byte[]) public static String uploadFile(String uploadPath, String originalName, byte[] fileData) throws Exception { // ★ 1. 고유값 생성 UUID uid = UUID.randomUUID(); String savedName = uid.toString() + "_" + originalName; // ★ 2. 년/월/일' 정보 생성 String savedPath = calcPath(uploadPath); // ★ 3. 원본파일 저장 File target = new File(uploadPath + savedPath, savedName); FileCopyUtils.copy(fileData, target); // ★ 4. 이미지 일경우 썸네일 이미지 생성 후 url 주소로 반환 String formatName = originalName.substring(originalName.lastIndexOf(".") + 1); String uploadedFileName = null; if (MediaUtils.getMediaType(formatName) != null) { // 이미지일 경우 썸네일 생성 후 이미지 이름 반환 ( 경로+년월일+s_이름) uploadedFileName = makeThumbnail(uploadPath, savedPath, savedName); } else { uploadedFileName = makeIcon(uploadPath, savedPath, savedName); } // 파일 경로를 -> url 경로로 변경해서 반환 return uploadedFileName; } // ckeditor 전용 업로드 파일 반환 된값이 썸네일이 아닌 원본 이미지 // 1.파일의 저장 경로(uploadPath), 2.원본 파일의 이름(originalName), 3.파일 데이터(byte[]) public static String ckuploadFile(String uploadPath, String originalName, byte[] fileData) throws Exception { // ★ 1. 고유값 생성 UUID uid = UUID.randomUUID(); String savedName = uid.toString() + "_" + originalName; // ★ 2. 년/월/일' 정보 생성 String savedPath = calcPath(uploadPath); // ★ 3. 원본파일 저장 File target = new File(uploadPath + savedPath, savedName); FileCopyUtils.copy(fileData, target); // ★ 4. 이미지 생성 후 url 주소로 반환 String uploadedFileName = makeIcon(uploadPath, savedPath, savedName); // 파일 경로를 -> url 경로로 변경해서 반환 return uploadedFileName; } // 이미지가 아닐경우 단지 파일 경로를 -> url 경로로 변경해서 반환 private static String makeIcon(String uploadPath, String savedPath, String savedName) { String iconName = uploadPath + savedPath + File.separator + savedName; return iconName.substring(uploadPath.length()).replace(File.separatorChar, '/'); } // 파일이 저장될 '년/월/일' 정보 생성 private static String calcPath(String uploadPath) { Calendar cal = Calendar.getInstance(); // 역슬래시 + 2017 String yearPath = File.separator + cal.get(Calendar.YEAR); // /2017 +/+ 10 한자리 월 일경우 01, 02 형식으로 포멧 String monthPath = yearPath + File.separator + new DecimalFormat("00").format(cal.get(Calendar.MONTH) + 1); // /2017/10 +/ + 22 String datePath = monthPath + File.separator + new DecimalFormat("00").format(cal.get(Calendar.DATE)); // 년월일 폴더 생성하기 makeDir(uploadPath, yearPath, monthPath, datePath); logger.info(" datePath - {}", datePath); return datePath; } // 실질 적인 날짜 폴더 생성 private static void makeDir(String uploadPath, String... paths) { if (new File(paths[paths.length - 1]).exists()) { // 년 월 일 에서 일 배열 paths 에서 paths -1 은 일 즉 해당일의 폴더가 존재하면 return return; } for (String path : paths) { File dirPath = new File(uploadPath + path); if (!dirPath.exists()) { // 년 월일에 대한 해당 폴더가 존재하지 않으면 폴더 생성 dirPath.mkdir(); } } } // 썸네일 이미지 생성하기 // 1.파일 경로 2. 년월일 경로, 3. 파일 이름 private static String makeThumbnail(String uploadPath, String path, String fileName) throws Exception { // 파일 존재하는 이미지를 메모리상 이미지에 올려 붙인다. 즉 메모리에 로딩시킨다. BufferedImage sourceImg = ImageIO.read(new File(uploadPath + path, fileName)); // 메모리상 이미지를 정해진 크기에 맞게 복사한다. BufferedImage destImage = Scalr.resize(sourceImg, Scalr.Method.AUTOMATIC, Scalr.Mode.FIT_TO_HEIGHT, WIDTH_SIZE); // 썸네일 이미지 이름을 정한다. 썸네일 이미지를 앞에 s_ 붙인다. String thumbnailName = uploadPath + path + File.separator + "s_" + fileName; // 파일 경로의 객체를 생성한다. File newFile = new File(thumbnailName); // 경로의 마지막 에 . 으로 중심으로 분리해서 .jpg, png, jpeg gif 의 문자를 추출한다. String formatName = fileName.substring(fileName.lastIndexOf(".") + 1); // 실질적인 썸네일 이미지를 복사한다. ImageIO.write(destImage, formatName.toUpperCase(), newFile); // 파일 경로인 역슬러시를 url 의 경로인 슬러시로 변경해서 해서 반환시킨다. return thumbnailName.substring(uploadPath.length()).replace(File.separatorChar, '/'); } }
2) 스프링의 resources 폴더를 사용할 경우
package config.upload; import java.io.File; import javax.servlet.http.HttpServletRequest; public class UploadPath { public static String attach_path = "resources/upload/"; public static String path(HttpServletRequest request) { String uploadPath = ""; try { String root_path = request.getServletContext().getRealPath("/"); uploadPath = root_path + attach_path.replace('/', File.separatorChar); } catch (Exception e) { e.printStackTrace(); } return uploadPath; } }
3. url 보여줄 주소 설정
public ResponseEntity<byte[]> disPlay(String fileName, String uploadPath) throws Exception{ //fileName 은 /년/월/일/파일명의 형태로 입력을 받는다. InputStream in=null; //ResponseEntity<byte[]> 로 결과는 실제로 파일의 데이터가 된다. //컨트롤에서 @ResponseBody 를 이용해야 하며 //byte[] 데이터가 그대로 전송될 것임을 명시한다. ResponseEntity<byte[]> entity=null; logger.info("File NAME : "+ fileName); try{ String formatName =fileName.substring(fileName.lastIndexOf(".")+1); MediaType mType =MediaUtils.getMediaType(formatName); HttpHeaders headers =new HttpHeaders(); // 경로 +/년/월/일 /파일이름 in =new FileInputStream(uploadPath+fileName); if(mType!=null){ //이미지인 경우 headers.setContentType(mType); }else{ //이미지가 아닌 경우 //MIME 타입을 다운로드 용으로 사용되는 'application/octet-stream 으로 지정한다. //브라우저는 이 MIME 타입을 보고 사용자에게 자동으로 다운로드 창을 열어 준다. fileName=fileName.substring(fileName.indexOf("_")+1); //한글 깨짐 방지 설정 //다운로드 할 때 사용자에게 보이는 파일의 이름이므로 한글 처리를 해서 // 전송합니다. 한글 파일의 경우 다운로드 하면 파일의 이름이 깨져서 // 나오기 반드시 인코딩 처리를 할 필요가 있다. String attach="\""+new String(fileName.getBytes("UTF-8"), "ISO-8859-1")+"\""; headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.add("Content-Disposition", "attachment; filename="+attach); } //실제로 데이터를 읽는 부분은 commons 라이브러리의 기능을 활용해서 대상 // 파일에서 데이터를 읽어내는 IOUtils.toByteArray() 이다. entity=new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED); }catch(Exception e){ e.printStackTrace(); entity=new ResponseEntity<byte[]>(HttpStatus.BAD_REQUEST); }finally{ in.close(); } return entity; }
@ResponseBody @RequestMapping("/displayFile") public ResponseEntity<byte[]> displayFile(String fileName) throws Exception{ UploadFileDisplay display=UploadFileDisplay.getInstance(); return display.disPlay(fileName, uploadPath); }
4. 반환될 자바스크립트 설정
응답해서 보여줄 자바스크립트는 다음과 같다.
샘프로 코드는 php 이다.
<script type='text/javascript'> window.parent.CKEDITOR.tools.callFunction($callback, $url, $message); </script>
callback 값은 다음과 같은 파라미터로 가져오면 된다.
String callback =request.getParameter("CKEditorFuncNum");
url 은 파일을 저장 후에 이미지를 출력해주는 url 을 적으면 된다.
출력 글은 바로 앞 글에서 적었다.
<a href='/displayFile?fileName="+년월일 이미지명+"' ><img src='/displayFile?fileName="+년월일 이미지명+"'/></a>
message =이미지를 업로드 했습니다.
전체 소스
UploadPath
/** * <pre> * 1. 패키지명 : config.upload * 2. 타입명 : UploadPath.java * 3. 작성일 : 2017. 10. 24. 오후 8:32:41 * 4. 저자 : 최준호 * * </pre> * */ package config.upload; import java.io.File; import javax.servlet.http.HttpServletRequest; public class UploadPath { public static String attach_path = "resources/upload/"; public static String path(HttpServletRequest request) { String uploadPath = ""; try { String root_path = request.getServletContext().getRealPath("/"); uploadPath = root_path + attach_path.replace('/', File.separatorChar); } catch (Exception e) { e.printStackTrace(); } return uploadPath; } }
UploadFileUtils
/** * <pre> * 1. 패키지명 : net.macaronics.web.controller * 2. 타입명 : test2.java * 3. 작성일 : 2017. 10. 24. 오후 7:40:39 * 4. 저자 : 최준호 * * </pre> * */ package config.upload; import java.awt.image.BufferedImage; import java.io.File; import java.text.DecimalFormat; import java.util.Calendar; import java.util.UUID; import javax.imageio.ImageIO; import org.imgscalr.Scalr; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.FileCopyUtils; public class UploadFileUtils { private static final Logger logger = LoggerFactory.getLogger(UploadFileUtils.class); private static Integer WIDTH_SIZE = 100; public static Integer getWIDTH_SIZE() { return WIDTH_SIZE; } public static void setWIDTH_SIZE(Integer wIDTH_SIZE) { WIDTH_SIZE = wIDTH_SIZE; } // 1.파일의 저장 경로(uploadPath), 2.원본 파일의 이름(originalName), 3.파일 데이터(byte[]) public static String uploadFile(String uploadPath, String originalName, byte[] fileData) throws Exception { // ★ 1. 고유값 생성 UUID uid = UUID.randomUUID(); String savedName = uid.toString() + "_" + originalName; // ★ 2. 년/월/일' 정보 생성 String savedPath = calcPath(uploadPath); // ★ 3. 원본파일 저장 File target = new File(uploadPath + savedPath, savedName); FileCopyUtils.copy(fileData, target); // ★ 4. 이미지 일경우 썸네일 이미지 생성 후 url 주소로 반환 String formatName = originalName.substring(originalName.lastIndexOf(".") + 1); String uploadedFileName = null; if (MediaUtils.getMediaType(formatName) != null) { // 이미지일 경우 썸네일 생성 후 이미지 이름 반환 ( 경로+년월일+s_이름) uploadedFileName = makeThumbnail(uploadPath, savedPath, savedName); } else { uploadedFileName = makeIcon(uploadPath, savedPath, savedName); } // 파일 경로를 -> url 경로로 변경해서 반환 return uploadedFileName; } // ckeditor 전용 업로드 파일 반환 된값이 썸네일이 아닌 원본 이미지 // 1.파일의 저장 경로(uploadPath), 2.원본 파일의 이름(originalName), 3.파일 데이터(byte[]) public static String ckuploadFile(String uploadPath, String originalName, byte[] fileData) throws Exception { // ★ 1. 고유값 생성 UUID uid = UUID.randomUUID(); String savedName = uid.toString() + "_" + originalName; // ★ 2. 년/월/일' 정보 생성 String savedPath = calcPath(uploadPath); // ★ 3. 원본파일 저장 File target = new File(uploadPath + savedPath, savedName); FileCopyUtils.copy(fileData, target); // ★ 4. 이미지 생성 후 url 주소로 반환 String uploadedFileName = makeIcon(uploadPath, savedPath, savedName); // 파일 경로를 -> url 경로로 변경해서 반환 return uploadedFileName; } // 이미지가 아닐경우 단지 파일 경로를 -> url 경로로 변경해서 반환 private static String makeIcon(String uploadPath, String savedPath, String savedName) { String iconName = uploadPath + savedPath + File.separator + savedName; return iconName.substring(uploadPath.length()).replace(File.separatorChar, '/'); } // 파일이 저장될 '년/월/일' 정보 생성 private static String calcPath(String uploadPath) { Calendar cal = Calendar.getInstance(); // 역슬래시 + 2017 String yearPath = File.separator + cal.get(Calendar.YEAR); // /2017 +/+ 10 한자리 월 일경우 01, 02 형식으로 포멧 String monthPath = yearPath + File.separator + new DecimalFormat("00").format(cal.get(Calendar.MONTH) + 1); // /2017/10 +/ + 22 String datePath = monthPath + File.separator + new DecimalFormat("00").format(cal.get(Calendar.DATE)); // 년월일 폴더 생성하기 makeDir(uploadPath, yearPath, monthPath, datePath); logger.info(" datePath - {}", datePath); return datePath; } // 실질 적인 날짜 폴더 생성 private static void makeDir(String uploadPath, String... paths) { if (new File(paths[paths.length - 1]).exists()) { // 년 월 일 에서 일 배열 paths 에서 paths -1 은 일 즉 해당일의 폴더가 존재하면 return return; } for (String path : paths) { File dirPath = new File(uploadPath + path); if (!dirPath.exists()) { // 년 월일에 대한 해당 폴더가 존재하지 않으면 폴더 생성 dirPath.mkdir(); } } } // 썸네일 이미지 생성하기 // 1.파일 경로 2. 년월일 경로, 3. 파일 이름 private static String makeThumbnail(String uploadPath, String path, String fileName) throws Exception { // 파일 존재하는 이미지를 메모리상 이미지에 올려 붙인다. 즉 메모리에 로딩시킨다. BufferedImage sourceImg = ImageIO.read(new File(uploadPath + path, fileName)); // 메모리상 이미지를 정해진 크기에 맞게 복사한다. BufferedImage destImage = Scalr.resize(sourceImg, Scalr.Method.AUTOMATIC, Scalr.Mode.FIT_TO_HEIGHT, WIDTH_SIZE); // 썸네일 이미지 이름을 정한다. 썸네일 이미지를 앞에 s_ 붙인다. String thumbnailName = uploadPath + path + File.separator + "s_" + fileName; // 파일 경로의 객체를 생성한다. File newFile = new File(thumbnailName); // 경로의 마지막 에 . 으로 중심으로 분리해서 .jpg, png, jpeg gif 의 문자를 추출한다. String formatName = fileName.substring(fileName.lastIndexOf(".") + 1); // 실질적인 썸네일 이미지를 복사한다. ImageIO.write(destImage, formatName.toUpperCase(), newFile); // 파일 경로인 역슬러시를 url 의 경로인 슬러시로 변경해서 해서 반환시킨다. return thumbnailName.substring(uploadPath.length()).replace(File.separatorChar, '/'); } }
CkeditorUploadController
/** * <pre> * 1. 패키지명 : config.upload * 2. 타입명 : CkeditorUploadController.java * 3. 작성일 : 2017. 10. 24. 오후 7:56:02 * 4. 저자 : 최준호 * * </pre> * */ package config.upload; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.io.PrintWriter; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; @Controller public class CkeditorUploadController { private static final Logger logger = LoggerFactory.getLogger(CkeditorUploadController.class); //파일 디렉토리 사용시 @Resource(name="uploadPath") private String uploadPath; //1.파일 디렉토리 사용 @RequestMapping(value="/ckeditorupload") public void imageUpload(HttpServletRequest request, HttpServletResponse response, @RequestParam MultipartFile upload ) throws Exception{ //1.CKEditor 에서 파일을 넘겨주는 이름이 upload 로 설정 되어 있다. 반드시 upload 로 설정 //헤더 설정 response.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=utf-8"); PrintWriter printWriter =response.getWriter(); String uploadFile=""; String fileUrl=""; String message=""; //2. 물리적 실제 저장소 에 저장하기 // 보안상 , jpg, jpeg, png, gif, 만 업로드 되도록 수정 if(UploadSecurity.check(upload)){ uploadFile=UploadFileUtils.ckuploadFile(uploadPath, upload.getOriginalFilename(), upload.getBytes()); logger.info(" uploadFile - {}" ,uploadFile); //3.URL 상에서 볼수 있는 이미지 경로 // /displayFile?fileName="+ fileName; fileUrl ="/displayFile?fileName="+ uploadFile; message="'이미지를 업로드 했습니다.'"; }else{ message="'이미지 파일이 아닙니다.'"; } String callback =request.getParameter("CKEditorFuncNum"); //4.스크립트 작성 StringBuffer sbuffer =new StringBuffer(); sbuffer.append("<script>window.parent.CKEDITOR.tools.callFunction("); sbuffer.append(callback); sbuffer.append(", '"); sbuffer.append(fileUrl); sbuffer.append(" ' , "+message); sbuffer.append(") </script>"); printWriter.println(sbuffer.toString()); printWriter.flush(); } //년월일 별로 분리하지않고 이미지 보안 처리 안하고 그냥 업로드 - request.getServletContext().getRealPath("/") 사용 @RequestMapping(value="/ckeditorupload2") public void imageUpload2(HttpServletRequest request, HttpServletResponse response, @RequestParam MultipartFile upload ) throws Exception{ //CKEditor 에서 파일을 넘겨주는 이름이 upload 로 설정 되어 있다. 반드시 upload 로 설정 //헤더 설정 response.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=utf-8"); OutputStream out =null; PrintWriter printWriter =null; String fileName =upload.getOriginalFilename(); //첨부 파일 이름 byte[] bytes =upload.getBytes(); //첨부파일을 바이트 배열로 저장 //String uploadPath ="업로드할 디렉토리 경로" + fileName; //물리적 실제 저장소 //UploadPath 를 사용시 String uploadPath =UploadPath.path(request) +fileName; out=new FileOutputStream(new File(uploadPath)); out.write(bytes); //서버에 파일 업로드 String callback =request.getParameter("CKEditorFuncNum"); printWriter=response.getWriter(); //URL 상에서 볼수 있는 이미지 경로 // String fileUrl =request.getContextPath()+"/upload/"+ fileName; String fileUrl ="/resources/upload/"+ fileName; String script="<script>window.parent.CKEDITOR.tools.callFunction("; script +=callback; script +=", '"; script +=fileUrl; script +=" ' , '이미지를 업로드 했습니다.'"; script +=") </script>"; printWriter.println(script); printWriter.flush(); } //3.년월일 별로 분리및 보안 처리 사용 - request.getServletContext().getRealPath("/") 사용 // 1번과 차이점은 UploadPath.path(request) 의 물리적 주소와 와 // fileUrl ="/resources/upload/"+ uploadFile; url 상의 //경로 차이뿐이 없다. @RequestMapping(value="/ckeditorupload3") public void imageUpload3(HttpServletRequest request, HttpServletResponse response, @RequestParam MultipartFile upload ) throws Exception{ //1.CKEditor 에서 파일을 넘겨주는 이름이 upload 로 설정 되어 있다. 반드시 upload 로 설정 //헤더 설정 response.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=utf-8"); PrintWriter printWriter =response.getWriter(); String uploadFile=""; String fileUrl=""; String message=""; //2. 물리적 실제 저장소 에 저장하기 // 보안상 , jpg, jpeg, png, gif, 만 업로드 되도록 수정 if(UploadSecurity.check(upload)){ uploadFile=UploadFileUtils.ckuploadFile(UploadPath.path(request), upload.getOriginalFilename(), upload.getBytes()); logger.info(" uploadFile - {}" ,uploadFile); //3.URL 상에서 볼수 있는 이미지 경로 // /displayFile?fileName="+ fileName fileUrl ="/resources/upload/"+ uploadFile; message="'이미지를 업로드 했습니다.'"; }else{ message="'이미지 파일이 아닙니다.'"; } String callback =request.getParameter("CKEditorFuncNum"); //4.스크립트 작성 StringBuffer sbuffer =new StringBuffer(); sbuffer.append("<script>window.parent.CKEDITOR.tools.callFunction("); sbuffer.append(callback); sbuffer.append(", '"); sbuffer.append(fileUrl); sbuffer.append(" ' , "+message); sbuffer.append(") </script>"); printWriter.println(sbuffer.toString()); printWriter.flush(); } @RequestMapping(value="/ckeditorform") public String ckeditorTest(){ return "test/ckeditor"; } }
ckeditor.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Macaronics.net</title> <!-- 합쳐지고 최소화된 최신 CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> <!-- 부가적인 테마 --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css"> <!-- 합쳐지고 최소화된 최신 자바스크립트 --> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> <script src="//cdn.ckeditor.com/4.7.3/standard/ckeditor.js"></script> </head> <body> <h1> </h1> <div class="row"> <div class="col-xl-2 col-sm-2"></div> <div class="col-xl-8 col-sm-8"> <table class="table"> <tr> <td>내용</td> <td class="span12"><textarea rows="5" class="form-control" name="content"></textarea> <!-- textarea 를 ckeditor 로 변경 시킴 --> </tr> </table> </div> </div> <script> CKEDITOR.replace("content", { filebrowserUploadUrl : "/ckeditorupload3" // filebrowserImageUploadUrl: 'MacaronicsServlet?command=ckeditor_upload' }); </script> </body> </html>
제작 : macaronics.net - Developer Jun Ho Choi
소스 : 소스가 필요한 분은 비밀 댓글로 작성해 주세요.
댓글 ( 7)
댓글 남기기