pastebase64toserver.zip [1.22 KB]

CKEditor에 이미지를 복사 붙여넣기 할 경우

다음과 같이 이미지 태그에 주소가입력되어 삽입됩니다.

<img alt="Google" src="https://www.google.co.kr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"/>
<br/>

<br/>

이렇게 타 서버의 이미지 주소를 삽입하게되면

추후 타 서버에서 이미지파일을 삭제할 경우 엑스박스를 보게 될 것입니다....😞

<br/>

아마 이런 문제점을 다른 개발자들도 인지를 하고 있었고 <a href="https://ckeditor.com/cke4/addon/pastebase64" target="_blank">pasteBase64</a>라는 플러그인을 확인하였습니다.

해당 플러그인을 설치하면 이미지 태그에 서버 주소가 들어가는 것이 아니라, 이미지를 다음과 같이 base64로 인코딩되어 삽입됩니다.

<img src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />
<br/>

<br/>

<br/>

하지만 여기서 작은 문제가 하나 발생합니다.

고용량의 이미지를 base64 형태로 인코딩하여 database에 삽입되는것은 상당히 무거운 작업입니다

SELECT할때도 무거운데이터를, UPDATE할때도 무거운데이터를 컨트롤하게 됩니다.

<br/>

방법을 찾아야겠습니다.

인코딩된 base64를 Ajax를 태워 바로 서버에 보내고, 본 서버의 URL을 받아 이미지 태그에 삽입하는 방법을 생각했습니다.

이렇게 구현하면 위의 두가지 문제점을 해결 할 수 있을 것입니다.! 👏

<br/>

우선 기존에 있던 pasteBase64 플러그인의 소스크도를 확인하면, 클립보드에 있는 이미지파일을 걸러 base64로 인코딩하는 로직이 있습니다.

로직을 더하여 인코딩된 base64를 Ajax로 서버단으로 날려, 이미지파일로 저장하게 할 것입니다.

저장 후 이미지 URL을 받아, 이미지 태그에 주소를 담아 삽입하면 작업이 완료됩니다!

<br/>

코드의 일부를 보면 다음과 같습니다.

/*** -- ***/
/**************/

function onPaste(event) {
        var editor = event.listenerData &amp;&amp; event.listenerData.editor;
        var $event = event.data.$;
        var clipboardData = $event.clipboardData;
        var found = false;
        var imageType = /^image/;

        if (!clipboardData) {
            return;
        }

        return Array.prototype.forEach.call(clipboardData.types, function (type, i) {
            if (found) {
                return;
            }

            if (type.match(imageType) || clipboardData.items[i].type.match(imageType)) {
            	return readImageAsBase64(clipboardData.items[i], editor, clipboardData.items.length > 1);
            }
        });
    }

    function readImageAsBase64(item, editor, useWorkAround) {
        if (!item || typeof item.getAsFile !== 'function') {
            return;
        }
        
        if(editor.config.pasteImageUrl){
	        var c = confirm("이미지를 서버에 저장하시겠습니까?");
	        if(c){
	        	var file = item.getAsFile();
	            var reader = new FileReader();
		        reader.onload = function (evt) {
		        	var base64 = evt.target.result;
		        	
		        	$.ajax({
		        		type	: "post",
		        		url 	: editor.config.pasteImageUrl,
		        		dataType: "JSON",
		        		async 	: false,
		        		data 	: {
		        			"base64" : base64
		        		},
		        		success : function(result) {
	        				var element = editor.document.createElement('img', {attributes: { src : result.path }});
							setTimeout(function () {
							    if (useWorkAround) {
							        var img = editor.getSelection().getRanges()[0].getBoundaryNodes().endNode;
							        if (img.$.tagName !== "IMG") {
							        img = img.getPrevious();
							    }
							    if (img &amp;&amp; img.$.tagName === "IMG") {
							            img.remove()
							        }
							    }
							    editor.insertElement(element);
							}, 10);
							
							return true;
		        		}
		        	});
		        }
		        
		        reader.readAsDataURL(file);
	        } else{
	        	return;
	        }
        }
    }


/*** -- ***/
/**************/
  • 4 : 붙여넣기시 발생하는 콜백함수를 말합니다.

  • 20 : 콜백함수가 호출되고 클립보드의 이미지파일을 확인하는 로직입니다.

  • 21 : 이미지 파일을 base64로 인코딩하는 함수를 호출합니다.

  • 32 : 이미지 파일을 서버에 저장할 것인지 확인받습니다. 아니라면 타서버 이미지 URL로 이미지태그를 생성 후 내용에 삽입됩니다.

  • 37 : base64로 인코딩된 이미지파일입니다.

  • 39 : Ajax를 이용하여 서버에 base64로 인코딩한 이미지파일을 저장합니다.

  • 48 : Ajax로 받은 이미지URL로 이미지태그를 생성후 내용에 삽입합니다.

<br/>

<br/>

그럼 이제 Ajax를 받은 백엔드는 다음과 같습니다.

	@ResponseBody
	@RequestMapping(value = "/mgnt/imgBase64Upload.do")
	public String blogDoImgUpload(HttpServletRequest request, String base64) throws IllegalStateException, IOException {
		String path = commonService.saveContentImage(base64);
		
		JSONObject result = new JSONObject();
		result.put("path", path);
		return result.toString();
	}
  • 3 : 파라미터로 base64 데이터를 받습니다.

  • 4 : base64파일을 이미지 파일로 저장합니다.

  • 8 : 저장한 경로를 반환합니다.

<br/>

<br/>

<hr/>

그럼 이제 결과를 확인해볼까요?

<br/>

<img src="https://file.podo-dev.com/blogs/images/2019/07/10/origin/YGFYGF181224235514.PNG" style="border-style:solid; border-width:1px"/>

클립보드의 이미지를 붙여넣기 하면 다음과 같이 서버에 저장할 것인지 확인받습니다.

<br/>

*** 확인을 누른경우**

<img src="/uploaded/temp/content_180713_160706_pasteImage.png"/>
<br/>

Ajax를 통해 본 서버에 업로드되었고 리턴받은 이미지 URL로 태그가 삽입됩니다.

<br/>

*** 취소를 누른경우**

<img alt="Google" src="https://www.google.co.kr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"/>

<br/>

타 서버 URL로 이미지태그가 삽입됩니다.

<br/>

<br/>

추가작업

  • Ckeditor, Ajax경로 설정
var editor = CKEDITOR.replace("study-contents", {
		height : '400px',
		filebrowserUploadUrl : getContextPath() + "/mgnt/imgUpload.do",
		pasteImageUrl : getContextPath() + "/mgnt/imgBase64Upload.do",
		on : {
			instanceReady : function( ev ){
			    // Output paragraphs as Text
.
			    this.dataProcessor.writer.setRules( 'p', {
			            indent : false,
			            breakBeforeOpen : true,
			            breakAfterOpen : false,
			            breakBeforeClose : false,
			            breakAfterClose : true
			        });
			}
		},
		toolbar : 'Full'
	});
  • 4 : 업로드 페이지에서 CKeditor 초기화 시, 해당 라인과 같이 Ajax 주소를 지정하도록 하였습니다.

<br/>

<br/>

  • Server.xml의 maxPostSize 설정.
<Connector connectionTimeout="20000" maxPostSize="-1" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
  • 1 : post 사이즈는 무제한이라고 알려져있는데 실제로 디폴트 값은 그렇지않습니다. 적절한 maxPostSize를 설정해줍니다.

<br/>

<br/>

  • Ckeditor, config.js에 플러그인 추가.
config.extraPlugins = 'pastebase64toserver';
  • 1 : 추가된 플러그인을 설정해줍니다.

<br/>

<br/>

<hr/>

다만 몇가지 한계점이 존재합니다.

  • 해당 기능은 GIF 이미지 파일은 작동하지 않습니다.

  • 클립보드에 텍스트 + 이미지파일을 복사하여 붙여넣기 하는 경우 작동하지 않습니다.

<br/>

<br/>

<br/>

0
이전 댓글 보기
등록
TOP