CKEditor5 사용 해보려다가.. 이미지 업로딩에 문제가 있어서 Summernote로 바꿔봤는데 괜찮은것같다.
우선 본인은 기존 부트스트랩 CSS와 겹치지 않는 lite버전을 사용했다.
프론트단에서 파일 업로드를 위한 코드를 서머노트 구현부분 콜백에 작성해준다.
$('#content').summernote({
minHeight: 500, // 최소 높이
maxHeight: null, // 최대 높이
focus: true, // 에디터 로딩후 포커스를 맞출지 여부
lang: "ko-KR", // 한글 설정
spellCheck: false,
**callbacks: { //이미지 첨부하는 부분
onImageUpload : function(files) {
uploadSummernoteImageFile(files[0],this);
}
}**
});
그리고 콜백에서 사용하는 onImageUpload ajax 함수를 구현한다.
function uploadSummernoteImageFile(file, editor) {
data = new FormData();
data.append("file", file);
$.ajax({
data : data,
type : "POST",
url : "/uploadSummernoteImageFile",
contentType : false,
processData : false,
success : function(data) {
//항상 업로드된 파일의 url이 있어야 한다.
$(editor).summernote('insertImage', data.url);
}
});
}
이것으로 프론트에서 설정하는 이미지 업로드 구현 설정이 끝났다. 앞으로는 백스테이지에서 작동하는 코드를 구현할 차례다.
compile group: 'commons-io', name: 'commons-io', version: '2.6'
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6'
spring.http.converters.preferred-json-mapper=gson
import com.google.gson.JsonObject;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
@Controller
public class FileManageController {
@PostMapping(value="/uploadSummernoteImageFile", produces = "application/json")
@ResponseBody
public JsonObject uploadSummernoteImageFile(@RequestParam("file") MultipartFile multipartFile) {
JsonObject jsonObject = new JsonObject();
String fileRoot = "C:\\summernote_image\\"; //저장될 파일 경로
String originalFileName = multipartFile.getOriginalFilename(); //오리지날 파일명
String extension = originalFileName.substring(originalFileName.lastIndexOf(".")); //파일 확장자
// 랜덤 UUID+확장자로 저장될 savedFileName
String savedFileName = UUID.randomUUID() + extension;
File targetFile = new File(fileRoot + savedFileName);
try {
InputStream fileStream = multipartFile.getInputStream();
FileUtils.copyInputStreamToFile(fileStream, targetFile); //파일 저장
jsonObject.addProperty("url", "/summernoteImage/"+savedFileName);
jsonObject.addProperty("responseCode", "success");
} catch (IOException e) {
FileUtils.deleteQuietly(targetFile); // 실패시 저장된 파일 삭제
jsonObject.addProperty("responseCode", "error");
e.printStackTrace();
}
return jsonObject;
}
}
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
//web root가 아닌 외부 경로에 있는 리소스를 url로 불러올 수 있도록 설정
//현재 localhost:8080/summernoteImage/1234.jpg
//로 접속하면 C:/summernote_image/1234.jpg 파일을 불러온다.
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/summernoteImage/**")
.addResourceLocations("file:///C:/summernote_image/");
}
}
이렇게 이미지 업로드 로직을 완성했다.
이미지 파일 Drag & Drop으로 업로드가 안될 경우 html&jsp에 다음 코드를 추가한다.
$("div.note-editable").on('drop',function(e){ for(i=0; i< e.originalEvent.dataTransfer.files.length; i++){ uploadSummernoteImageFile(e.originalEvent.dataTransfer.files[i],$("#summernote")[0]); } e.preventDefault(); })
완성!
Summernote의 기본 이미지 업로딩 방식은 Data URL Scheme으로 저장되어 실제 서비스에 사용하기엔 무리가 있다. 불러올 때 매우매우 느려지기 때문에 웬만하면 따로 이미지 업로드 로직을 추가하는것이 좋을것같다...