月亮

[ckeditor4] vuejs3에서 연동하고 이미지 업로드/다운로드를 구현해보자! 본문

시각화/ckeditor

[ckeditor4] vuejs3에서 연동하고 이미지 업로드/다운로드를 구현해보자!

듀네 2024. 4. 17. 18:05
원래는 ckeditor5로 잘쓰고 있었는데 이미지 업로드 쪽에서 사용자가 직접 사이즈를 입력하게끔하고 싶은데 마땅한 라이브러기가 없어서 인터넷을 뒤져보니 vue3+ckeditor4로 할 수 있는 방법이 있었다! 추가적으로는 이미지 업로드/다운로드를 설정한 과정도 기록해둔다.

 

  1. ckeditor를 직접 zip 파일로 받아야한다.

https://ckeditor.com/ckeditor-4/download/#ckeditor-4

 

CKEditor 4 - Download Latest Version

Download a ready-to-use Latest Version of CKEditor 4 package.

ckeditor.com

 

위의 링크에 들어가서 주의 할 점이 있다!

lts로 사용하지 않고 그냥 ckeditor4로 들어가서 다운을 받아야한다. 나는 커스템해서 만들었다.

아무튼 4.22.1 버전으로 받으면 된다고 생각하면 된다.

 

2. 다운로드 한것을 아래와 같이 public 폴더에 넣는다. 통째로 넣어주면 된다.

3. index.html 을 열고 아래와 같이 작성한다.

 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Welcome to Vuetify 3</title>

</head>
<body>
<script src="/public/ckeditor/ckeditor.js"></script>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
</body>

</html>

 

참고로 body안에 스크립트를 넣은 이유는 빌드할때 head에 넣으면 문제가 생긴다. head에 넣으면 절대경로 문제가 생겨서 빌드 파일안에 public 폴더를 찾는데 빌드 파일안에는 assets폴더뿐이라 문제가 생긴다. 로컬에서 할때는 어떤 방법이든 문제는 생기지 않지만 빌드 할 경우를 생각해서 바디 태그 안에 넣는게 좋다!

바디 태그안에 넣어주면 빌드 할때 아래처럼 잘 빌드해준다

 

<body>
    <script src="./ckeditor/ckeditor.js"></script>
    <div id="app"></div>
</body>

 

준비는 이제 끝!

4. 코드를 작성해보자

vue 파일을 하나 만들고

 

<template>
<textarea cols="80" id="editor1" name="editor1" rows="10"></textarea>
</template>

 

<stript setup lang=ts>
import { onMounted, ref } from "vue";
// 상대경로를 설정하고 import하는게 좋다. 나중에 빌드를 위해서 지금은 
//import custom from "../assets/custom.css?inline"; 해도되긴함
import custom from "@assets/ckeditorCustom.css?inline";

// 에디터를 담을 변수 만들기
let ckEditor: any = null;
// 에디터의 내용을 담을 변수
const param = ref({ contents: ""})

const createCkEditor = () => {
// config 지정
// 나는 필요한것만 지정해서 커스템했기 때문에 본인에게 맞는 설정으로 지정해야한다.
  ckEditor = window.CKEDITOR.replace("editor1", {
    toolbar: [
// header, fontstyle, fontsize
      {
        name: "styles",
        items: ["Format", "Font", "FontSize"],
      },
      {
        name: "basicstyles",
        items: [
          "Bold",
          "Italic",
          "Underline",
          "Strike",
          "RemoveFormat",
          "CopyFormatting",
        ],
      },
      {
        name: "colors",
        items: ["TextColor", "BGColor"],
      },
      {
        name: "align",
        items: ["JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock"],
      },
      {
        name: "paragraph",
        items: [
          "NumberedList",
          "BulletedList",
          "-",
          "Outdent",
          "Indent",
          "-",
          "Blockquote",
        ],
      },
      {
        name: "insert",
        items: ["Image", "Table"],
      },
      {
        name: "links",
        items: ["Link", "Unlink"],
      },
      {
        name: "clipboard",
        items: ["Undo", "Redo"],
      },
    ],
// header 설정
    extraAllowedContent:
      "h3{clear};h2{line-height};h2 h3{margin-left,margin-top}",
// autogrow는 에디터 전체 높이나 넓이를 설정하기 위해서 씀
    extraPlugins: "autogrow",
// image2를 써서 제외한듯
    removePlugins: "image",
// 아래의 url은 좀더 봐야겠지만 아래 처럼 설정하면 image upload api를 작성해주면됨
    filebrowserUploadUrl:
      import.meta.env.VITE_APP_API_SERVER_URL + "/file/upload",
    uploadUrl: import.meta.env.VITE_APP_API_SERVER_URL + "/file/upload",
    filebrowserBrowseUrl:
      import.meta.env.VITE_APP_API_SERVER_URL + "/file/upload",
    filebrowserImageBrowseUrl:
      import.meta.env.VITE_APP_API_SERVER_URL + "/file/upload",
    filebrowserImageUploadUrl:
      import.meta.env.VITE_APP_API_SERVER_URL + "/file/upload",
    autoGrow_minHeight: 220,
    autoGrow_maxHeight: 600,
    width: "100%",
    language: "ko",
// 스킨은 ckeditor4에 제공하는 스킨인데 이거도 다운로드해서 editor > skin 폴더에 넣으면됨 상관없으면 지정안해도됨
    //skin: "prestige",
// 에디터 내부의 css를 설정하고 싶을때 설정해야한다. global.css에 설정해도 에디터 안의 스타일은 절대 안바뀌고 따로
// assets 폴더 같은 곳에 custom.css를 하나 만들고 설정하면 잘 먹는다. 웹폰트도 여기에 설정하면 된다.
    contentsCss: custom,
//에디터 ui에 보여줄 이름/실제 폰트 이름;... 이런식으로 작성해야한다.
    font_names:
      "나눔고딕/Nanum Gothic;고운돋움/바탕체/RIDIBatang;",
// header 설정
    format_tags: "p;h1;h2;h3;pre;div",
    stylesSet: [
// 테이블 설정
      {
        name: "Compact table",
        element: "table",
        attributes: {
          cellpadding: "5",
          cellspacing: "0",
          border: "1",
        },
        styles: {
          "border-collapse": "collapse",
        },
      },
    ],
  });

// 이미지 업로시. Bearer 토큰을 넣어야 할 필요가 있어서 fileUploadRequest 이벤트로 이미지 업로드 api를
// 요청하기 직전에 같이 보내도록 세팅 했다. 이 기능이 필요없으면 삭제해도 무방하당
  ckEditor.on("fileUploadRequest", (evt) => {
    const xhr = evt.data.fileLoader.xhr;
    xhr.setRequestHeader("Authorization", `Bearer ${token}`);
    xhr.setRequestHeader(
      "enctype",
      `multipart/form-data; charset=utf-8; boundary=${makeBoundary()}`,
    )});

// 이미지를 업로드 했으면 다시 다운받아서 에디터에 보여줘야하는데 내가 만든 download api하고 형식이 안 맞아져서
// 이미지 사이즈나 파일을 불러오지 못하는 것 같아서 fileUploadResponse 이벤트를 이용해서 다운로드한 결과값을
// 수정해서 다시 에디터에 보내주도록 설정했다
  ckEditor.on("fileUploadResponse", (evt) => {
    evt.stop();
    const data = evt.data,
      xhr = data.fileLoader.xhr,
      response = xhr.responseText.split("|");

    if (response[1]) {
      data.message = response[1];
      evt.cancel();
    } else {
      try {
// 아래의 data.url가 다운로드 할 url을 적어준다. 본인의 api에 맞춰서 
//(response[0]는 이미지를 업로한 후 결과값으록 나의 경우에는 이미지를 업로한 주소, 파일 이름을 리턴값으로 주고
// 다운로드할때 param으로 사용했다)
        const jsonObject = JSON.parse(response[0]);
        const fileName = jsonObject.resultData.fileName;
        data.url =
          import.meta.env.VITE_APP_API_SERVER_URL +
          "/file/image/download/" +
          fileName;
      } catch (error) {
        console.error(
          "주어진 텍스트를 JSON 객체로 파싱하는 동안 오류가 발생했습니다:",
          error,
        );
        evt.cancel();
      }
    }
});

// 에디터의 내용이 변결될때 마다 param.contents에 값이 할당되도록 설정
  ckEditor.on("change", () => {
    param.value.contents = ckEditor.getData();
  });

// 아래는 참고 사항으로 만약에 에디터를 수정/등록 폼으로 만든다고 했을 때, 수정시에는 기존 값을 불러와야
// 하는데, 불러올때는 무조건 에디터가 랜더링 된 뒤에 데이터를 넣어줘야한다.
// instanceReady 이벤트는 에디터가 완전히 랜더링 된 후에 어떤 동작을 실핼 할 수 있게 해준다.
  ckEditor.on("instanceReady", () => {
    setDataInfo();
  });
};

const setDataInfo = () => {
    apiservice.get().then((d: any) => {
      const data = d.data.resultData;
      ckEditor.setData(data.contents);
    });
}

onMounted(() => {
    createCkEditor();
});
</sctript>

 

 

다음에는 api를 설명해볼까 생각중

참고

https://ckeditor.com/docs/ckeditor4/latest/guide/dev_file_upload.html

 

Uploading Dropped or Pasted Files | CKEditor 4 Documentation

Learn how to install, integrate and configure CKEditor 4. More complex aspects, like creating plugins, widgets and skins are explained here, too. API reference and examples included.

ckeditor.com

https://mine-it-record.tistory.com/277

 

[JavaScript] CKEditor4 사용하기 2 (적용 및 이미지 업로드)

- CKEditor4 적용 및 이미지 업로드 사용하기 - CKEditor를 사용하면서 이미지관련돼서 좀 헤맸는데 한번 알아보도록하자. 앞서 설치 및 다운로드까지 완료하여 불러오기까지 됐다면 태그를 가지고

mine-it-record.tistory.com

 

반응형
Comments