진이의 Developer Story
Spring MVC를 활용한 스마트에디터 2.0 이미지 업로드 본문
안녕하세요.
저희는 ckeditor를 사용하고 있었는데요.
클라이언트가 불편하다고 해서, 대체 에디터를 찾다가 스마트에디터를 발견했습니다.
(클라이언트가 가장 많이 쓰는건 엑셀에서 작업한 내용을 올리는 것이라고 했습니다.)
* 스마트에디터는 네이버에서 개발한 오픈 위지윅스입니다.
가장 좋은건 엑셀에서 표 붙여넣기 할때 가장 똑같이 만들어서 복사가 되더군요.
표를 제어할때도 편리하고요~
일단 변경하기에 앞서서 적용이 일단 잘 되어야 변경계획을 수립할지 결정을 하겠지요.
스마트에디터의 기능으로 html은 잘 작성이 되는데요.
문제는 이미지를 첨부할 때가 문제란 말이죠.
스마트에디터 내에서도 php는 기본적으로 지원이 되는데, 자바로는 포팅해서 사용해야 하더라구요.
인터넷을 찾아봐도 스프링에 맞춘 셋팅 방법은 나오지 않더라구요.
지금부터 이미지 업로드를 어떻게 하면 되는지 작성해보겠습니다.
스마트에디터를 다운받아주세요. [클릭]
링크로 이동하시면 지금까지 릴리즈된 스마트에디터를 버전별로 확인하실 수 있는데, 가장 최근 버전을 다운받으시면 되겠습니다.
그리고 압축을 풀어주시고, 그대로 프로젝트 내에 넣어주세요. (리소스 폴더내에 넣으면 되겠죠)
수정해야할 파일은 se2/photo_uploader/popup/attach_photo.js 입니다.
1. se2/photo_uploader/popup/attach_photo.js
스마트 에디터는 퀵 이미지 업로드를 제공하고 있습니다.
그런데 업로드는 2가지 방식입니다. (HTML5, HTML)
두 방식의 차이는 드래그앤드롭 지원여부입니다.
HTML5을 지원하는 브라우저에서는 드래그앤드롭,멀티업로드를 지원하고 있고, 그외의 브라우저는 단일파일업로드 입니다.
제가 소스를 훓어본 결과 HTML5는 form태그를 이용하지 않고 네이버 진도 프레임워크의 ajax를 활용하여 파일정보를 전송하고, HTML5는 form태그를 이용하여 네이버 진도 프레임워크의 form을 활용하여 보냅니다.
스프링에서 파일 업로드를 할때 MultipartFile을 활용하기 위해서는 폼 태그를 이용하여 전송을 하여만 합니다.
따라서 저는 HTML5 방식은 구현하지 않고 HTML 방식만 구현하겠습니다.
그러면 HTML5가 지원하는 브라우저에서도 일반 파일 업로드 방식으로 보여줘야합니다.
해당 파일에서 약 543라인 부근을 보시면 window.onload 이벤트에서 브라우저의 드래그앤드롭API 지원여부를 확인하여 분기하는 부분이 있는데, 이 부분을 강제로 HTML방식으로 고정하겠습니다.
window.onload = function(){
// checkDragAndDropAPI();
// if(bSupportDragAndDropAPI){
// $Element("pop_container2").hide();
// $Element("pop_container").show();
//
// welTextGuide.removeClass("nobg");
// welTextGuide.className("bg");
//
// addEvent();
// } else {
// $Element("pop_container").hide();
// $Element("pop_container2").show();
// callFileUploader();
// }
$Element("pop_container").hide();
$Element("pop_container2").show();
callFileUploader();
fnUploadImage = $Fn(uploadImage,this);
$Fn(closeWindow,this).attach(welBtnCancel.$value(), "click");
};
여기서 pop_container2, pop_container를 toggle 해주는 부분이 있는데,
pop_container는 HTML5 드래그앤드롭 방식이고, pop_container2는 일반 HTML 방식입니다.
이렇게 해주시면 파일업로드 버튼을 눌렀을때 뜨는 업로드 팝업이 무조건 HTML로 고정이 됩니다.
그리고 함수를 수정해주셔야 하는데요.
callFileUploader함수에서 sUrl을 본인의 controller URL로 매핑시켜주시면 스크립트 수정은 끝입니다.
이제 컨트롤러에서 MultipartFile로 받으셔서 처리를 해주시면 되는데, 중요한 점은 반
드시 sendRedirect를 해주셔야 한다는 점입니다.
콜백을 지정해주셔야 하는데요.
이를 지정해주셔야 파일을 업로드 하고나서, 에디터에 이미지 링크를 붙여넣을 수 있습니다. 콜백이 제대로 지정되지 않는다면 팝업창이 닫히지도 이미지 링크가 넣어지지도 않으므로 유의해주세요.
그럼 간단한 예제 메서드를 작성해보겠습니다.
public void se2ImageUpload(MultipartHttpServletRequest multiRequest, HttpServletResponse response) {
try {
String callback = multiRequest.getParameter("callback");
String callback_func = "?callback_func="+multiRequest.getParameter("callback_func");
String return_url = "";
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
(파일 업로드 코드...중략)
return_url += "&bNewLine=true";
return_url += "&sFileName="+fileNm();
return_url += "&sFileURL=/upload/"+date+"/"+newName+ "."+fileExt;
response.sendRedirect(callback+callback_func+return_url);
} catch (Exception e) {
e.printStackTrace();
}
return;
}
callback과 callback_func는 클라이언트에서 요청할 때 넘어오는 값입니다.
callback은 callback될 url 값이며, callback_func는 콜백함수로 스마트에디터 내에서 임의의 숫자를 5개를 조합하여 보내주는 값입니다.
return_url는 파일의 정보를 클라이언트에 보내주는 값입니다.
파라메터는 3가지가 있는데, 중요한건 FileName과 FileURL입니다.
FileName은 img 태그 내에 title 값으로 들어가게 되며, FileURL을 실제로 파일이 저장된 주소를 적어주시면 되겠습니다.
스마트에디터는 처음 사용해보는거라 사용법 익히는데 약간의 시간은 들었습니다만, 누군가는 이 글이 도움이 되기를 바라며 글을 마칩니다.
[추가 - HTML5 방식]
photo_upload.html 아래 코드 추가
<!-- //footer --> </div> // 이 아래 부분에 추가합니다. <form enctype="multipart/form-data" style="display: none;"> <input id="file" type="file"> </form>
attach_photo.js 수정
function callAjaxForHTML5 (tempFile, sUploadURL){
var oAjax = jindo.$Ajax(sUploadURL, {
type: 'xhr',
method : "post",
onload : function(res){ // 요청이 완료되면 실행될 콜백 함수
var sResString = res._response.responseText;
if (res.readyState() == 4) {
if(sResString.indexOf("NOTALLOW_") > -1){
var sFileName = sResString.replace("NOTALLOW_", "");
swal("경고", "이미지 파일(jpg,gif,png,bmp)만 업로드 하실 수 있습니다. ("+sFileName+")", "warning");
}else{
//성공 시에 responseText를 가지고 array로 만드는 부분.
makeArrayFromString(res._response.responseText);
}
}
},
timeout : 3,
onerror : jindo.$Fn(onAjaxError, this).bind()
});
var formData = new FormData();
document.getElementById("file").files[0] = tempFile;
formData.append("file", document.getElementById("file").files[0]);
oAjax.request(formData);
}
callAjaxForHTML5 함수를 수정합니다.
대략 6줄정도 수정해주시면 되는데요.
tempFile(파일오브젝트)를 input 에 추가를 해준 뒤, 해당 input을 formData 객체에 담아서 보내면 MultipartFile로 받을 수 있습니다.
그렇다면 무슨 차이가...?
여기서 핵심은 jindo Ajax를 호출할 때 Content-Type을 명시해서 보내주게 될 경우 body부분이 payload 형식으로 보내지게 됩니다.
이렇게 보낼 경우는 HttpServletRequest로밖에 받을 수 없게 되는거죠.
흔히 아는 inputStream, outputStream을 이용해서 파일 데이터를 받아야 되는겁니다.
몇시간 헤멘 끝에 결국 해결은 했네요...
도움되시길 바라며!!
'Java > Spring' 카테고리의 다른 글
스프링 Maven Project - GIT - 젠킨스(jenkins) 연동하기 (1) | 2016.11.24 |
---|---|
Spring JavaMailSender 를 이용하여 메일보내기 (0) | 2016.11.17 |
Apache PDFBOX (pdf to image) (1) | 2016.10.27 |
(6) Spring+MyBatis 게시판 만들기 - 수정 및 삭제 추가 (12) | 2016.10.19 |
HTML TO EXCEL, PDF (0) | 2016.09.29 |