summernote À̹ÌÁö ¾÷·Îµå ±¸Çö ¹æ¹ý - ½æ¸Ó³ëÆ® À̹ÌÁö ¾÷·Îµå
- summernote À̹ÌÁö ¾÷·Îµå ±¸Çö ¹æ¹ý -
summernote´Â base64·Î ÀÎÄÚµù ÈÄ ÀúÀåÇÏ´Â ¹æ½ÄÀÌ¿©¼ À̹ÌÁö ÆÄÀÏ °ü¸®°¡ ¾î·Æ´Ù.
±×·¡¼ callbackÀ» ÀÌ¿ëÇÏ¿© À̹ÌÁö¸¦ ƯÁ¤ °æ·Î¿¡ ¾÷·Îµå ÈÄ °íÀ¯ÇÑ url¸¦ ¸®ÅÏÇÏ´Â ¹æ½ÄÀ¸·Î ±¸ÇöÇÑ´Ù.
ÀÌ °úÁ¤¿¡¼ urlÀ» ÅëÇÑ ¿ÜºÎ ¸®¼Ò½º Á¢±ÙÀ» À§ÇÑ ÅèĹ ¼³Á¤µµ ÇØÁà¾ß ÇÑ´Ù.
spring boot ¸¦ ±âÁØÀ¸·Î ¼³¸íµÈ ±ÛÀÔ´Ï´Ù.
1. summernote ¼¼Æà ¹× À̹ÌÁö ÆÄÀÏ ¾÷·Îµå callback ÇÔ¼ö ±¸Çö
½á¸Ó³ëÆ®¿¡¼´Â ¸î°³ÀÇ callback ÇÔ¼ö¸¦ Áö¿øÇÑ´Ù.
±× Áß À̹ÌÁö¸¦ ¾÷·ÎµåÇÒ ¶§ »ç¿ëÇÒ callback ÇÔ¼ö´Â onImageUpload ¶õ ÇÔ¼öÀÌ´Ù.
onPaste ÇÔ¼ö(º¹ºÙ¿¡ ´ëÇÑ Äݹé) ´Â - ±âº»°ªÀ» »ç¿ëÇÏ¸é º¹ºÙ½Ã base64·Î ÀÎÄÚµùµÈ src À̹ÌÁö ÆÄÀÏ°ú onImageUpload¿¡¼ ±¸ÇöÇÑ url ±â¹ÝÀÇ À̹ÌÁö ÆÄÀÏÀÌ µÎ°³°¡ µé¾î°¡´Â ¹ö±×°¡ »ý±ä´Ù, µû¶ó¼ ¾Æ·¡¿Í °°ÀÌ Àç ¼³Á¤À» ÇØÁØ´Ù.
$('#summernote').summernote({
height: 300, // ¿¡µðÅÍ ³ôÀÌ
minHeight: null, // ÃÖ¼Ò ³ôÀÌ
maxHeight: null, // ÃÖ´ë ³ôÀÌ
focus: true, // ¿¡µðÅÍ ·ÎµùÈÄ Æ÷Ä¿½º¸¦ ¸ÂÃâÁö ¿©ºÎ
lang: "ko-KR", // ÇÑ±Û ¼³Á¤
placeholder: 'ÃÖ´ë 2048ÀÚ±îÁö ¾µ ¼ö ÀÖ½À´Ï´Ù', //placeholder ¼³Á¤
callbacks: { //¿©±â ºÎºÐÀÌ À̹ÌÁö¸¦ ÷ºÎÇÏ´Â ºÎºÐ
onImageUpload : function(files) {
uploadSummernoteImageFile(files[0],this);
},
onPaste: function (e) {
var clipboardData = e.originalEvent.clipboardData;
if (clipboardData && clipboardData.items && clipboardData.items.length) {
var item = clipboardData.items[0];
if (item.kind === 'file' && item.type.indexOf('image/') !== -1) {
e.preventDefault();
}
}
}
}
});
/**
* À̹ÌÁö ÆÄÀÏ ¾÷·Îµå
*/
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);
}
});
}
l
2. pom.xml¿¡ gson , commons-io maven Ãß°¡ (Çʼö ¾Æ´Ô)
ÆÄÀÏ ¾÷·Îµå ·ÎÁ÷°ú JSONÀ» ¸®ÅÏÇϱâ À§ÇÑ gson »ç¿ë
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
2-1. application.properties¿¡ json ÄÁ¹öÅ͸¦ gsonÀ¸·Î ¼¼Æà (2 »ý·«½Ã »ý·« °¡´É)
ÀÌ°Å ¼³Á¤ ¾ÈÇÏ°í JsonObject ¸®ÅÏÇÏ¸é ¿À·ù³´Ù.
#spring json ±âº» ÄÁ¹öÅÍ°¡ jackson À̹ǷΠgson À¸·Î ÄÁ¹öÅͽà ¿À·ù°¡ ¹ß»ýÇؼ ±âº»À» gsonÀ¸·Î º¯°æ
spring.http.converters.preferred-json-mapper=gson
3. ÄÁÆ®·Ñ·¯¿¡¼ ÆÄÀÏ ¾÷·Îµå ·ÎÁ÷ ±¸Çö
¼¸Ó³ëÆ®·Î ¾÷·ÎµåÇÑ À̹ÌÁö¸¦ À¥·çÆ®¿¡ ¾÷·ÎµåÇعö¸®¸é ÇÏ¸é ºôµåÇÏ°í Àç¹èÆ÷½Ã À̹ÌÁö°¡ ´Ù »ç¶óÁö´Ï ¿ÜºÎ °æ·Î¿¡ Àâ¾ÆÁØ´Ù.
@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(".")); //ÆÄÀÏ È®ÀåÀÚ
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;
}
4. ¿ÜºÎ ¸®¼Ò½º °æ·Î ÅèĹ¿¡ ¸ÅÇÎ
À̹ÌÁö ¾÷·Îµå¿¡¼ °¡Àå »ðÁúÇß´ø ºÎºÐÀÌ´Ù. ¿ÜºÎ ¸®¼Ò½º¸¦ ÅèĹ¿¡¼ Á¢±ÙÀ» ÇؾßÇϴµ¥ °è¼Ó °æ·Î ¿À·ù°¡³ª¼ ¸î½Ã°£µ¿¾È ã¾Ò´Âµ¥ file:// -> file:/// ·Î /À» 3¹øÀ» ½á¾ßÇϴµ¥ 2¹øÀ» ½á¼ ±×·¨´Ù.
Àß È®ÀÎÇÏÀÚ.
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:8090/summernoteImage/1234.jpg
//·Î Á¢¼ÓÇϸé C:/summernote_image/1234.jpg ÆÄÀÏÀ» ºÒ·¯¿Â´Ù.
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/summernoteImage/**")
.addResourceLocations("file:///C:/summernote_image/");
}
}
¾÷·Îµå µÈ ȸé
À̹ÌÁö ¾÷·Îµå°¡ ¿Ï·áµÇ¸é ´ÙÀ½°ú °°ÀÌ url·Î Á¢±ÙÀ» ÇϰԵȴÙ.
ÇÏ´Ùº¸´Ï±î µå·¡±× ¾Ø µå¶øÀÌ ¾ÈµÇ´Â °æ¿ì°¡ ÀÖ´Ù. ±×·¯¸é ÇÏ´ÜÀÇ Äڵ带 Ãß°¡ÇÑ´Ù. ( summernote »ý¼ºÇÑ ´ÙÀ½ ÄÚµå)
µå·¡±× ¾Ø µå¶øÀ¸·Î À̹ÌÁö ÷ºÎ°¡ ¾È µÈ´Ù¸é ¹ØÀÇ Äڵ带 Ãß°¡ÇÑ´Ù.
$("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();
})