JavaScript È°¿ëÆÁ
2021.01.18 / 01:27

summernote À̹ÌÁö ¾÷·Îµå ±¸Çö ¹æ¹ý - ½æ¸Ó³ëÆ® À̹ÌÁö ¾÷·Îµå

ÇϾá¼Ò
Ãßõ ¼ö 261

- 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·Î Á¢±ÙÀ» ÇϰԵȴÙ.

¾÷·Îµå µÈ È­¸é
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();
   })