상세 컨텐츠

본문 제목

[Meta ESG] SmartEditor2 에디터 내 이미지 추가 구현 | SpringBoot, Azure blob storage

Project/Meta ESG

by yooputer 2024. 1. 18. 08:51

본문

Meta ESG 프로젝트에서 에디터 내 이미지 삽입 요건이 있었다.

에디터는 SmartEditor2를 사용하였고, SmartEditor2에 구현되어있던 이미지 모듈에 

이미지를 클라우드에 업로드하고 이미지 경로를 반환하는 api를 사용해 구현하였다.


스마트 에디터2 설치

공식 문서를 참고해 스마트 에디터2를 설치하였다.

https://naver.github.io/smarteditor2/user_guide/2_install/setting.html

 

2.0 버전 설치 · GitBook

No results matching ""

naver.github.io


사진 플러그인 추가

아래 문서를 참고해 사진 플러그인을 추가했다.

https://naver.github.io/smarteditor2/user_guide/4_photouploader/install/01.html

 

사진 플러그인 추가 · GitBook

No results matching ""

naver.github.io


attach_photo.js 수정

기존 코드는 php기반이고 오류가 너무 많았어서 직접 구현하였다.

html5Upload 함수와 setPhotoToEditor 함수를 수정하였다.

 

html5Upload 함수 수정

/**
 * HTML5 DragAndDrop으로 사진을 추가하고, 확인버튼을 누른 경우에 동작한다.
 * @return
 */
function html5Upload() {
    for(var j=0, k=0; j < nImageInfoCnt; j++) {
        let imgFile = htImageInfo['img' + j];
        let formData = new FormData();
        formData.enctype = "multipart/form-data";
        formData.method = "POST";

        formData.append("imageFile", imgFile);

		// 1)
        let token = opener.parent.parent.document.getElementsByName('_csrf')[0].getAttribute('content');
        let header = opener.parent.parent.document.getElementsByName('_csrf_header')[0].getAttribute('content');

		// 2)
        jQuery.ajax({
            url: "/file/upload-editor-image-ajax",
            type: "POST",
            data: formData,
            enctype: "multipart/formdata; charset=utf-8",
            processData: false,
            contentType: false,
            cache: false,
            beforeSend: function (jqXHR, settings) {
                if (token && header) {
                    jqXHR.setRequestHeader(header, token);
                }
            },
            success: function (imageTag) {
                setPhotoToEditor(imageTag)
            },
            error: function (e) {
                console.log(e);
                alert("사진 업로드에 실패했습니다.");
            }
        });
    }

    goReadyMode()
    
    // 3)
    // window.close(); 
}
  1. 스프링 시큐리티를 사용중인데, csrf 토큰이 없으면 403 에러가 뜨기 때문에 팝업 호출자의 document에서 csrf를 찾아서 헤더에 넣어주었다.
  2. 서버에 이미지를 보내면 서버는 이미지를 클라우드에 업로드하고 이미지의 경로를 img 태그에 넣어서 반환한다.
  3. window.close() 주석을 해제하면 오류가나는데 디버깅을 못해서 그냥 주석처리 해놨다. (디버깅 해야지...)

 

setPhotoToEditor 함수 수정

에디터 안에 이미지 태그를 넣어주는 코드다. 

oFileInfo는 서버에서 받은 img태그이다.

function setPhotoToEditor(oFileInfo){
    if (!!opener && !!opener.nhn && !!opener.nhn.husky && !!opener.nhn.husky.PopUpManager) {
        //본문에 바로 tag를 넣는 방법 (oFileInfo는 String으로 <img src=....> )
        opener.nhn.husky.PopUpManager.setCallback(window, 'PASTE_HTML', [oFileInfo]);
    }
}

컨트롤러 메서드 구현

@Controller
@RequestMapping("/file")
@RequiredArgsConstructor
public class FileController extends CommonController{

    private final FileService fileService;

    /**
     * 에디터 이미지 업로드 api
     *
     */
    @PostMapping("/upload-editor-image-ajax")
    @ResponseBody
    public String singleImageUpload(MultipartFile imageFile){
        try{
            return fileService.uploadSingleEditorImageAndGetImageTag(imageFile);
        }catch (Exception e){
            logger.error("Exception", e);
            throw new AjaxException(e);
        }
    }

}

서비스 메서드 구현

uploadSingleEditorImageAndGetImageTag 메서드 구현

FileUtil을 통해 파일을 저장하고 이미지 태그를 만들어 반환한다.

public String uploadSingleEditorImageAndGetImageTag(MultipartFile imageFile) {
    String fileName = imageFile.getOriginalFilename();
    FileUtil.checkFileExtension(fileName, "image");

    String savePath = FileUtil.getEditorImagePath();
    String fileURL = FileUtil.savePublicFileAndGetFileUrl(imageFile, savePath);

    String imageTag = String.format("<img src=\"%s\" alt=\"%s\" style=\"width: 400px; margin: 0px;\">", fileURL, fileName);

    return imageTag;
}

FileUtil 구현

getEditorImagePath메서드 구현

이미지 파일을 저장할 경로를 반환한다

public static String getEditorImagePath(){
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");
    return ServerInfoUtil.getUploadPath()+"PUBLIC/EDITOR_IMAGE/" + sdf.format(new Date());
}

 

savePublicFileAndGetFileUrl메서드 구현

파일을 저장 후 파일url을 반환한다.

파일 서버로는 Azure Blob Storage를 사용하였는데, ResourceLoader를 사용하여 업로드하기 위해서는 사전에 파일서버 설정이 필요하다.

public static String savePublicFileAndGetFileUrl(MultipartFile multipartFile, String filePath) {
    if (multipartFile == null) {
        throw new CustomException(ErrorCode.FILE_NOT_FOUND);
    }

    String saveName = UUID.randomUUID().toString();
    String fullPath = filePath + saveName;
    String fileURL = null;

    Resource storageBlobResource = resourceLoader.getResource(fullPath);
    try (OutputStream os = ((WritableResource) storageBlobResource).getOutputStream()) {
        os.write(multipartFile.getBytes());
        fileURL = storageBlobResource.getURI().toString();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

    return fileURL;
}

 

관련글 더보기