1. tika 라이브러리 추가
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>2.7.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency>
2. 컨트롤
Ckeditor 4, Ckeditor 5 통합
Ckeditor 5는 post 방식
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.IOUtils;
import org.apache.tika.Tika;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import lineage.choco.util.config.MediaUtils;
@Controller
public class FileUploadController {
@Value("${upload.path}")
public String uploadDirectory;
@ResponseBody
@RequestMapping("/displayFile")
public ResponseEntity<byte[]> displyFile(String fileName) throws Exception {
if (fileName == null || !StringUtils.hasText(fileName)) {
return new ResponseEntity<byte[]>("0".getBytes(), HttpStatus.BAD_REQUEST);
}
InputStream in = null;
ResponseEntity<byte[]> entity = null;
try {
String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
MediaType mType = MediaUtils.getMediaType(formatName);
HttpHeaders headers = new HttpHeaders();
in = new FileInputStream(uploadDirectory + fileName);
if (mType != null) {
headers.setContentType(mType);
} else {
fileName = fileName.substring(fileName.indexOf("_") + 1);
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 (Exception e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return entity;
}
@RequestMapping(value="/ckeditor/image/upload")
@ResponseBody
public Map<String, Object> ckeditor4(HttpServletRequest request, @RequestParam MultipartFile upload ) throws Exception{
Map<String, Object> map=new HashMap<>();
InputStream inputStream = upload.getInputStream();
if(isPermisionFileMimeType(inputStream)) {
String uploadFile=ckuploadFile(uploadDirectory, upload.getOriginalFilename(), upload.getBytes());
String fileUrl = request.getContextPath()+"/displayFile?fileName=" + uploadFile;
map.put("uploaded", 1);
map.put("fileName", upload.getOriginalFilename());
map.put("url", fileUrl);
return map;
}
return null;
}
/**
* Tika 로 업로드 파일 검사
*/
private boolean isPermisionFileMimeType( InputStream inputStream ) throws Exception {
final String[] PERMISSION_FILE_MIME_TYPE = {"image/gif", "image/jpeg", "image/png", "image/bmp"};
String mimeType = new Tika().detect(inputStream);
for( int i = 0; i < PERMISSION_FILE_MIME_TYPE.length; i++ ) {
if( PERMISSION_FILE_MIME_TYPE[i].equals(mimeType) ) {
return true;
}
}
return false;
}
// 1.파일의 저장 경로(uploadPath), 2.원본 파일의 이름(originalName), 3.파일 데이터(byte[])
private 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);
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();
}
}
}
}
3. 화면처리
1)ckeditor 4
ckeditor 4 다운드 받은 후 분리하기 귀찮으면 통으로 resources 파일 위치에 업로드 후 다음과 같이 적용.
글쓴이는 Full Package ckeditor 4 를 다운로드 받은후 스프링부트의 static 위치 디렉토리에서 lib/ckeditor/ 디렉토리 만든후 통으로 업로드 처리.
https://ckeditor.com/ckeditor-4/download/
파일을 다운로드 받으면 config.js 있는데 해당 파일에 옵션값을 넣어주면 된다.
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Nanum+Gothic:wght@400;700;800&family=Noto+Sans+KR:wght@300;400;500;700;900&display=swap" rel="stylesheet">
/**
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see https://ckeditor.com/legal/ckeditor-oss-license
*/
CKEDITOR.editorConfig = function( config ) {
// Define changes to default configuration here. For example:
// config.language = 'fr';
// config.uiColor = '#AADC6E';
config.language = 'ko';
config.uiColor = '#aeb8e3';
config.height = 700;
config.toolbarCanCollapse = true;
//config.font_defaultLabel ='나눔';
config.fontSize_defaultLabel ='12px';
config.font_names = '나눔/Nanum Gothic;노토산/Noto Sans KR;굴림/Gulim;돋움/Dotum;바탕/Batang;궁서/Gungsuh;맑은 고딕/Malgun;Arial/arial;Comic Sans MS/comic;Courier New/cour;Georgia/georgia;Lucida Sans/LSANS;Tahoma/tahoma;Times New Roman/times;Trebuchet MS/trebuc;Verdana/verdana;'; // 사용 가능한 폰트 설정
};
<script src="/resources/lib/ckeditor/ckeditor.js"></script>
<textarea id="content" name="content"></textarea>
<scirpt>
CKEDITOR.replace('content',
{
filebrowserUploadUrl:'/ckeditor/image/upload'
}
);
<script>
내용입력
CKEDITOR.instances.content.setData('<p>데이터</p>')
내용가져오기
CKEDITOR.instances.content.getData()
2 ) ckeditor 5는 cdn 적용
<script src="https://cdn.ckeditor.com/ckeditor5/36.0.1/classic/ckeditor.js"></script>
<script src="https://cdn.ckeditor.com/ckeditor5/36.0.1/classic/translations/ko.js"></script>
<textarea id="content" name="content"></textarea>
<script>
let ckeditor;
ClassicEditor.create(document.querySelector('#content'), {
ckfinder: {
uploadUrl: `/ckeditor/image/upload`
},
language: 'ko'
})
.then(editor => {
ckeditor = editor;
})
.catch(error => {
console.error(error);
});
</script>
내용 가져오기 const content = ckeditor.getData();

















댓글 ( 4)
댓글 남기기