생활코딩

Coding Everybody

파일 업로드 & CKEditor

토픽 생활코딩 > 서버 > PHP > CodeIgniter

수업소개

이번 수업에서는 오픈소스 위지윅 에디터인 CKEditor을 이용해서 파일을 서버로 전송하고, 전송된 데이터를 CI의 upload 라이브러리 클래스로 받아서 저장하는 방법에 대해서 알아본다. 이 과정에서 위지윅 에디터를 적용하는 방법에 대해서도 익힐 수 있다. 순수 HTML을 이용해서 파일을 업로드 하는 방법은 CodeIgniter의 메뉴얼을 참고한다. 

선행지식

Upload Class

초기화

CodeIgniter의 업로드 클래스는 더 적은 코드로 더 안전하게 파일을 전송 할 수 있는 방법을 제공하고 더 많은 경우에 대한 예외처리를 제공한다. 이 클래스를 초기화 할 때는 아래와 같이 한다. 

// 사용자가 업로드 한 파일을 /static/user/ 디렉토리에 저장한다.
$config['upload_path'] = './static/user';
// git,jpg,png 파일만 업로드를 허용한다.
$config['allowed_types'] = 'gif|jpg|png';
// 허용되는 파일의 최대 사이즈
$config['max_size'] = '100';
// 이미지인 경우 허용되는 최대 폭
$config['max_width']  = '1024';
// 이미지인 경우 허용되는 최대 높이
$config['max_height']  = '768';
$this->load->library('upload', $config);

파일저장

 upload 클래스의 핵심 메소드는 do_upload이다. 이것을 실행하면 서버로 전송된 파일의 보안 취약점을 점검하고 문제가 없으면 지정된 디렉토리로 파일을 이동시킨 후에 실행 결과를 리턴한다. 아래와 같이 사용한다. 

$field_name = "some_field_name";
$this->upload->do_upload($field_name)

$file_name 값은 file type의 폼에서 지정한 name 값과 일치해야 한다. 예를들면 아래와 같아야 한다. 

<input type="file" name="some_field_name" />

CKEditor

CKEditor는 위지윅 에디터다. 위지윅(WYSIWYG)이란  What You See Is What You Get 한국어로는 보는데로 얻는다는 뜻으로, HTML 코드 없이 포맷을 편집할 수 있는 기능을 제공하는 에디터다. CKEditor는 무료고 오픈소스로 사용할 수 있는 대표적인 위지윅 에디터다. 

CKEditor을 설치하기 위해서는 다운로드 받아야 한다. 아래 주소를 방문해서 최신버전을 다운로드 받자. 

다운받은 파일을 /static/lib 디렉토리에 풀고 위지윅 에디터가 필요한 페이지에 textarea를 만든 후에 CKEditor 파일을 페이지에 로드한다.  그리고 textarea와 CKEditor를 자바스크립트로 연결해주면 간단하게 설치가 완료된다. 아래는 최소한의 코드다.

<html>
    <head>
        <script src="/static/lib/ckeditor/ckeditor.js"></script>
    </head>
    <body>
        <form>
            <textarea name="description">            
            </textarea>
            <script>
                CKEDITOR.replace( 'description' );
            </script>
        </form>
    </body>
</html>

 이미지 업로드 기능 활성화

CKEditor에서 이미지 업로드 기능을 활성화시키기 위해서는 CKEditor를 textarea에 연결할 때 옵션 값을 전달해야 한다. 위의 코드를 아래와 같이 수정한다. 

<script>
    CKEDITOR.replace( 'description', {
        filebrowserUploadUrl: '/topic/upload'
    });
</script>

툴바 중에 이미지 버튼을 누르고 업로드 탭을 선택한 후에 파일을 전송하면 /topic/upload로 파일이 전송된다. /topic/upload는 CKEditor가 전송한 파일을 받아서 보안 취약점을 점검한 후에 문제가 없으면 파일을 저장한다. 

업로드 후 처리

업로드 정보를 받아서 처리한 /topic/upload 는 CKEditor에 업로드한 파일을 삽입 할 수 있도록 미리 약속된 callback 함수를 호출해야 한다. callback의 형식은 아래와 같다. 

<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction('콜백의 식별 ID 값', '파일의 URL', '전송완료 메시지')</script>
  • 콜백의 식별 ID 값 : CKEditor가 파일을 전송할 때 자동으로 'CKEditorFuncNum'라는 GET 타입의 데이터를 전송한다. 이 값을 그대로 사용하면 된다. 
  • 파일의 URL : 저장된 파일에 접근 할 수 있는 URL. CKEditor는 이 값을 이용해서 이미지를 본문에 저장한다.
  • 전송완료 메시지 : 전송된 결과를 사용자에게 보여주는 메시지

예제

예제 코드가 많아짐에 따라서 본문에 포함시키기가 어려워지고 있다. 따라서 앞으로는 github의 링크를 걸도록 하겠다. 

태그

참고

댓글

댓글 본문
  1. 존레논아부지
    완료~ !! 구뜨~

    파일업로드는 걍 마이 스타일로~ ㅎㅎ
    감사합니다~
  2. 이병철
    CKEditor 5 upload.php 찾다 찾다 열받아서 그냥 짰습니다. 다행히 잘 되네요.

    <?
    $ofilename = $_FILES['upload']['name'];
    $filesize = $_FILES['upload']['size'];

    // 파일 확장자 구해서 결과를 뿌려준다.
    $ext = explode(".",$ofilename);
    $ext = strtolower(end($ext));

    $mt = substr(microtime(),3,5);


    $output_dir = $_SERVER['DOCUMENT_ROOT']."/images/upload/";
    $src_ufilename = "src_".date('YmdHis').'_'.$mt.".$ext";
    $src_ufilename_dir = "{$output_dir}$src_ufilename";


    $r = move_uploaded_file($_FILES["upload"]["tmp_name"], $src_ufilename_dir);

    if($r==1)
    {
    $fileurl = "/images/upload/$src_ufilename";

    $data = array('uploaded' => true, 'url' => $fileurl);

    $list = json_encode($data, JSON_PRETTY_PRINT+JSON_UNESCAPED_UNICODE);
    echo $list;

    }
    ?>
  3. 헤이영
    CI3 / CKEditor4 에서 확인 내용

    CKEDITOR 자바스크립트 항목에 filebrowserUploadMethod 를 추가해주면 다른 부분 수정 없이 가능

    <script>
    CKEDITOR.replace('description', {
    'filebrowserUploadMethod': 'form', // 이부분 추가
    'filebrowserUploadUrl': '/topic/upload_receive_from_ck'
    });
    </script>
  4. jeisyoon
    2021.09.21 Ci 4 & ckEditor 5 환경에서 성공

    2021.08.25 Ci 2 완강하고 08.26 부터 09.21까지 --------------------------------------------
    Ci 4 & ckEditor 5 simple Image upload 를 자습함
    Ci 4 나 ckEditor 5 환경이 너무 많이 바뀌어 처음 부터 앱을 새로 만들어야 함.

    -----------------Ci 2 or 3 --> Ci 4 로 Upgrade -------------------------------------
    Ci 4는 프레임워크는 새로 만들어졌으며 이전 버전과 호환되지 않습니다.
    앱을 업그레이드하는 대신 마이그레션하는 것이 좋습니다.
    http://ci4doc.cikorea.net......tml

    ------------- Ci 4 Introduce Tutorials --------------------------------------------------------------------------
    Ci 4 한글 사이트 http://ci4doc.cikorea.net......tml
    Ci 4 Simple Blog- #1 https://www.youtube.com......LOE
    Ci 4 Simple Blog- #2 https://www.youtube.com......PN4
    (영어로 강의를 하나 Ci 2 를 완강 하였다면 코딩하는 것을 따라가면 언어는 문제가 안됨)

    --------------- Ci 4 Image Upload Tutorial -----------------------------------------------------------
    Ci 4 Form Scratch #11-Form validation
    https://www.youtube.com......8q8
    Ci 4 Form Scratch #12-Validation & File Upload
    https://www.youtube.com......8q8
    Ci 4 Form Scratch #12-Image Manipulation
    https://www.youtube.com......mzc
    (영어로 강의를 하나 Ci 2 를 완강 하였다면 코딩하는 것을 따라가면 언어는 문제가 안됨)

    --------------- Ci 4 & ckEditor Simple Image Upload Tutorial ------------------------------------
    ckEditor 5 install - online build : https://ckeditor.com......er/
    ckEditor 5 Simple upload Adaptor
    : https://ckeditor.com......tml

    ------- ckeditor 5 에서 Server 전송 후 (/topic/ckEditor_recive) 구현 -------------------------------------------
    Ci 4 에서 ckEditor 5 를 구현하는 Tutorials가 없어 찾는데만 7일 걸림.
    -----------------------------------------------------------------------------------------------------------------------------
    public function ckEditor_receive(){
    helper(['form', 'image']);
    $data = [];

    if ($this->request->getMethod() == 'post') {
    $rules = [
    'upload' =>[
    'rules' => 'uploaded[upload]|max_size[upload, 10240]|is_image[upload]',
    'label' => 'The Upload',
    ]
    ];

    if ($this->validate($rules)) {
    $file = $this->request->getFile('upload');
    if($file->isValid() && !$file->hasMoved()) {
    $file->move('./uploads/images');
    $fileName = $file->getName();

    // Ckeditor Return Value seting -----------------------
    $data = [
    'uploaded' => true,
    'url' => '/uploads/images/'.$fileName,
    ];
    } else {
    $data = [
    'uploaded' => false,
    'errors' => [
    'messages' => '/uploads/images/'.$fileName,
    'validation' => $this->validator,
    ]
    ];
    }
    }
    // CkEditor Call Back Function ------------
    return $this->response->setJSON($data);
    }
    }
    ------------------------------------------------------------------------------------------------------------------------
  5. jeisyoon
    2021.08.21 File Upload - OK : CKEditor - Fail

    이미지가 업로드 미리보기와 Edit 화면, List 보기 등에 는 안보이고
    image File에는 Upload 되었음

    3일 동안 문제 해결을 하려 하였으나 실패

    1. 선행 학습자의 조언에 따라 시도 실패,
    2. CKEditor 4.16.2 Standard, 4.8.0 & 4.7.3 으로 시도 실패,
    3. Disk Cash 삭제 후 시도 실패,
    4. CKEditor 4.16.2 Image upload 시도 실패,

    오래전 강의 내용이라 개발 환경이 많이 바뀌어 해결하기 너무 힘들어
    이 강의를 마치고 CodeIgniter 4, CKEditor 5 최종버전으로 다시 도전 예정.
  6. 미댈
    세번째 영상에서 이미지 업로드 안돼서 한참 찾았네요..

    ckeditor의 config.js 파일에 아래 소스 추가

    CKEDITOR.editorConfig = function( config ) {
    ... 생략 ...
    config.filebrowserUploadMethod = 'form';
    };
  7. CrashOverride
    같은 방식으로 업로드에 실패했을 경우에는

    echo "<script>alert('업로드에 실패 했습니다. ".$this->upload->d isplay_errors('','')."')</script>";

    이 코드를

    echo '{"uploaded": 0, "error": {"message": "'.$this->upload->displ ay_errors('','').'"}}';

    이렇게 바꾸니 잘 작동하네요~
    대화보기
    • 복받으세요! 덕분에 해결했습니다
      대화보기
      • CKEditor 4.11 에서 실습하다가 문제가 발생하여 아래 해결한 링크 공유합니다.

        증상: URL GET방식으로 에디터에서 자동으로 추가 해주는 파라미터가 안되는 이슈
        ㄴ 안넘어옴~!!! CKEditor,langCode,CKEditorFuncNum
        https://stackoverflow.com......num

        ex)
        희망하는 URL
        http://localhost......=ko

        문제의 URL
        http://localhost......_ck

        저 같은경우는 CKEditor config.js 수정후 크롬같은경우 강제 새로고침하여 하니깐 잘 작동하더라구요.

        // All browsers will use a plain form element to upload the file.
        config.filebrowserUploadMethod = 'form';

        *코드 추가하고 크롬에서 새로고침 해도 문제있길래... 30분간 인터넷만 뒤적뒤적하다 혹시나해서 파폭에서 테스트했는데요. 정상작동... 그리고 드는생각은... 캐시를 안비웠구나...

        암튼 같은 문제가있으신분들은 도움이 되셨으면 하는마음에서 올립니다 :)
      • 지니
        서버 오류 메시지가 떠서 고생했는데 도움이 많이 되었네요^^ 감사합니다.
        대화보기
        • KyungHyun So
          파일 폼 링크가 사라졌습니다!
        • jenny
          어렵네요ㅜ
          파일 서버로 전송하고 확인 버튼 누른후 글 게시하면 이미지가 안뜨는데 왜이럴까요
        • 수박바
          CKEditor 4.10 버전에서는 아래에 '응답없음' 문제가 해결이 안되네요..
          할 수 없이 4.8 버전으로 내려왔습니다.
        • 2일찾음
          5버전도 여기가 하이라이트 부분입니다.


          echo '
          {
          "fileName": "'.$data['upload_data']["file_name"].'",
          "uploaded": 1,
          "url": "\/static\/user\/'.$data['upload_data']["file_name"].'"
          }
          ';

          아래분이 작성하신 부분
        • phphtmldb
          CKEditor5로 이미지 파일 업로드 방법 아시는분 도움 좀 주세요~
        • https://sdk.ckeditor.com......ges
          https://docs.ckeditor.com......tml
          https://docs.ckeditor.com......oad

          CKEditor4 이미지 파일 업로드 관련 공식 메뉴얼 링크 입니다.
          이미지파일 업로드 후에 스크립트로 콜백함수를 호출을 하는 방식이 아닌
          json 양식으로 결과값 노출시키는 방식으로 변경이 되었네요.

          핵심은
          echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction('콜백의 식별 ID 값', '파일의 URL', '전송완료 메시지')</script>

          이 부분이

          echo '
          {
          "fileName": "'.$data['upload_data']["file_name"].'",
          "uploaded": 1,
          "url": "\/static\/user\/'.$data['upload_data']["file_name"].'"
          }
          ';

          이렇게 바뀌어야 합니다.


          그리고
          https://github.com......ter
          이것은 여기 강좌를 따라해서 만들고 있는 제 깃허브 주소 입니다.

          특정 API 사용법을 파악하는 것이라 그냥 샘플 소스보는 것이 가장 이해가 빠른데
          그것을 못 찾아서 전 한참 헤멧네요.
          참고하실 분들은 참고하세요.
        • 정의로운삶
          3일 동안 찾았습니다
          감사합니다 ^^
          대화보기
          • Deuklyoung Ko
            아래 문제에 관한 CKEditor4 메뉴얼을 찾아 보았습니다.

            https://docs.ckeditor.com......hod

            4.9.0 버전부터 옵션값이 추가 되면서 기본 설정 값이 수정이 된 것 같네요.

            관련 참고페이지
            https://docs.ckeditor.com......lly


            * CKEditor 5, 너는 누구냐 ㅜㅜ;
            https://support.ckeditor.com......-4-
          • 하루날려먹음
            아.. 아래 "날려버린 나의 3일" 님과 "똘똘이박사"님과 같은 현상으로 어제부터 계속 고생했네요.;;;
            알려주신 것으로 이것저것 다 해보면서 해봤는데.. 저는 안되더라고요.. 계속 똑같이 잘못된 서버 응답 오류가..

            그러다가 구글에 열심히 검색하고 아주 간단하게 해결하였습니다.
            ckeditor 의 config.js에
            config.filebrowserUploadMethod = 'form';
            위의 한줄 추가만 하면 끝~
            echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction('".$CKEditorFuncNum."', '".$url."', '전송에 성공 했습니다')</script>";
            위의 것 그대로 놔두고 config.js에 위의 항목만 추가하면 됩니다.
          • 똘똘이박사
            오~ 날려버린 나의 3일님 감사합니다.
            저도 그 문제로 지금 거의 한달가까이 진행 못하고 있다가
            님의 힌트 덕분에 해결했습니다.
            CK4.9.2 버전을 사용했는데 뭔가 내부적으로 변화가 있나 보네요
            암튼 정말 고맙습니다~^^
          • 날려버린 나의 3일
            CI 3.0
            CK 4.0 에서 이미지 업로드시 잘못된 서버 응답 오류로 몇일 고생하다가
            커뮤니티에서 어떤분 댓글로 성공했습니다.

            echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction('".$CKEditorFuncNum."', '".$url."', '전송에 성공 했습니다')</script>";
            이부분을

            echo '{"filename" : "'.$filename.'", "uploaded" : 1, "url":"'.$url.'"}';

            이렇게 해보세요 화이팅!
          • 1234
            업로드 실패시 파일 선택폼 유지코드
            - 실패시에도 callFunction을 해야합니다 (인자는 false로)

            function upload_receive_from_ck(){
            $config['upload_path'] = './public/uploads/user';
            // git,jpg,png 파일만 업로드를 허용한다.
            $config['allowed_types'] = 'gif|jpg|png';
            // 허용되는 파일의 최대 사이즈
            $config['max_size'] = '2000';
            // 이미지인 경우 허용되는 최대 폭
            $config['max_width'] = '2048';
            // 이미지인 경우 허용되는 최대 높이
            $config['max_height'] = '1536';
            $this->load->library('upload', $config);

            $CKEditorFuncNum = $this->input->get('CKEditorFuncNum');
            if ( ! $this->upload->do_upload("upload"))
            {
            $msg = "'{$this->upload->display_errors(false,false)}'";
            $url ="false";
            }
            else
            {
            $data = $this->upload->data();
            $filename = $data['file_name'];

            $msg = "false";
            $url = "'/public/uploads/user/{$filename}'";
            }
            echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction('{$CKEditorFuncNum}', {$url}, {$msg} )</script>";
            }
          • orez
            예제 코드가 빠져서 아쉬워요.ㅠㅠ.. 좀 많더라도 함꼐 올려주셨으면 좋겠습니다.
            git은 할 줄 몰라서 식별이 쉽지 않습니다.
          • will
            업로드까지만하고 글쓰던거 취소해버리면
            업로드했던 파일은 쓸모가없어서 지워야되는데
            그과정은 어떻게 깔끔하게 처리할수있을지 음....
          • 김세창
            잘배웠습니다~!! ㅎㅎ
          • 늦깎이
            작은선물님 덕분에 하나 해결했습니다. 감사합니다.
            대화보기
            • 작은선물
              CodeIgniter 3.1.1버전 이후 파일 업로드 시 php.ini에 php_fileinfo를 extension 해야합니다.
              저도 안되서 구글링해본결과 기존의 function _file_mime_type() 안에 함수가 변경되었다고 합니다.^^;
            • 신입1
              감사합니다.
            • 장루피나
              localhost에서 작업하면 이미지 업로드가 안되나요?
            • 정수리형
              강의 잘보고있습니다!! 많은 도움이 되요~!!
              그런데 이미지 업로드를 구현 한 후에 테스트를 해 보니, 파일은 업로드가 되는데, '전송완료 메시지'가 안뜨고, '예'를 눌러봐도 '이미지 소스 url이 없습니다'라는 메시지를 띄웁니다. 서버에서 파일을 받았는지 확인해보면 파일은 있구요. 주소창에 직접 url을 쳐서 들어가도 이미지가 출력됩니다. ck에디터상에서만 url을 못 따오는 것 같은데... 무엇이 문제일까요?
            • JustStudy
              고맙습니다
            • 잘보고 갑니다.
            • chase
              http://ckeditor.com......on7

              가능합니다.
              대화보기
              • $this->load->library('upload', $config);

                이부분이 무엇인가요?
              • uglyducklin
                github에 있는 파일을 그대로 다운받아 서버에 적용해봤는데요.

                The configuration file does not exist. 라는 문구가 나오는 이유는 무엇때문일까요 ㅠㅠ
              • will
                크롬브라우저에는 레이아웃 맞게 ck에디터가 잘들어갑니다.
                그러나 파이어폭스브라우저에서는 레이아웃이 자꾸 깨집니다.
                해결법은 잘모르겠습니다~
                참고들 하셔야할듯
              • 청아
                하....감사합니다
              • 양갱이
                안녕하세여 저는 지금 ckeditor를 이용해 홈페이지를 만들고 있는 사람입니다
                다름이 아니라 ckeditor로 이미지 올리기는 성공하였는데 파일을 올리고 싶습니다 이미지는 잘 올라가는데 파일이 올라가지 안더군요
                이미지랑 파일을 단순히 올리는 것 뿐만 아니라 사람들이 다운받아서 쓰는 기능도 만들어야 하는데 여기 ckeditor에서 할 수 없나요?
                저는 자바에서 개발을 하고 있고 jsp를 쓰고 있습니다
                사람들이 다운로드 받을 수 있게 하는 것도 구현하고 싶습니다
                도움을 주시면 감사하겠습니다 : )
              • 태양이
                오타있네요~
                $file_name 값은 file type의 폼에서 지정한 name 값과 일치해야 한다. 예를들면 아래와 같아야 한다.
                =>
                '$field_name' 값은 file type의 폼에서 지정한 name 값과 일치해야 한다. 예를들면 아래와 같아야 한다.
              • egoing
                그건 직접 구현하셔야 합니다:)
                대화보기
                • chobo
                  upload 클래스를 이용해서 aws s3로 올릴수는 없을까요...?
                • jio1122
                  정말감사합니다
                • 포포탄
                  강의 잘 보았습니다.

                  그런데 이미지 업로드를 구현 한 후에 테스트를 해 보니, 파일은 업로드가 되는데, '전송완료 메시지'가 안뜨고, '예'를 눌러봐도 '이미지 소스 url이 없습니다'라는 메시지를 띄웁니다. 서버에서 파일을 받았는지 확인해보면 파일은 있구요. 주소창에 직접 url을 쳐서 들어가도 이미지가 출력됩니다. ck에디터상에서만 url을 못 따오는 것 같은데... 무엇이 문제일까요?
                • 김승갑
                  진짜 좋은 강의입니다.
                • egoing
                  동영상은 업로드 하시는 것 보다는 youtube 등을 이용하시는 것을 추천 드립니다. 동영상 업로드는 별도의 복잡한 기술적인 도전 과제들이 필요합니다.
                  대화보기
                  • 목도리
                    잘봣습니다 ㅎㅎ근데 이미지가 아닌 동영상도 업롣가 가능한가요?
                  • 산넘어산
                    한글이름 파일을 업로드를 하면 한글이 깨져서 저장이 되는데 어떻게 처리 해야하나요?
                    iconv("UTF-8","EUC-KR",$filename) 이런 형식으로 변환말고 다른 방법은 없나요?
                    (로컬에서 테스트하고 있습니다)
                  • rrdna
                    csrf가 켜져 있으니 ck에디터에서 화일 첨부가 안됩니다.
                    csrf를 사용하면서 ckeditor를 사용할수는 없는것인지 알고 싶습니다.
                  • egoing
                    수정했습니다~
                    대화보기
                    • 리누즈토바르즈
                      PHP에서 파일을 다루는 방법 주소가 깨졋습니다 수정바랍니다!