본문으로 바로가기

이번 글에서는 PHP 프레임워크인 Codeigniter를 활용한 파일 업로드 예제를 올려보려고 한다. 현재 구현한 파일 업로드 로직은 이미지 파일만을 업로드할 수 있도록 구현되어있으며 AWS S3등의 클라우드에 맞춰 개발한것이 아닌 로컬 환경에서 작동하도록 구현했다. 그러므로 파일 업로드 위치는 htdocs폴더 내부의 public/upload/ 를 사용하고 있음을 알린다.

 

먼저 파일을 업로드하기 위한 폼을 먼저 만들도록 하겠다.

function upload_form() 
{
    if (http_method() == 'GET') 
    {
        echo '<h1>File Upload</h1>';
        echo '
            <form name="uploadForm" method="post" action="/1.0/api/upload" 
            enctype="multipart/form-data">
                <div>
                    <label for="upfile">첨부파일</label>
                    <input type="hidden" name="userId" id="userId value="testUser"/>
                    <input type="file" name="upfile" id="upfile"/>
                </div>
                <input type="submit" value="업로드"/>
            </form>
        ';
    }
    else
    {
        http_error(false);
    }
}

upload_form() 함수는 Rest API용도로 사용되고 있기 때문에 http mehtod가 get일 경우에만 접근을 허용한 모습이다. 

/1.0/api/upload 경로로 업로드한 파일을 전송하고 있으며 폼 타입은 multipart/form-data, 메소드는 post를 사용하고 있다. 이와같은 폼을 사용해 파일을 업로드할 경우 해당 경로로 바이너리가 전송된다. 

아래는 업로드된 파일을 처리하는 로직 함수이다.

function upload() 
{
    // axios환경에서는 file data, post data 둘다 받아서 파일명앞에 사용자 명과 식별자를 붙혀야 함
    if (http_method() == 'POST') 
    {
        if(isset($_FILES['upfile']) && $_FILES['upfile']['name'] != "") {
            $file = $_FILES['upfile'];
            $allowed_extensions = explode(',', "png,jpg,jpeg");
            $max_file_size = 5242880;
            $ext = substr($file['name'], strrpos($file['name'], '.') + 1); // 파일 확장자 반환

            // 확장자 체크
            if(!in_array($ext, $allowed_extensions)) {
                http_error('업로드할 수 없는 확장자입니다.');
            }

            // 파일 크기 체크
            if($file['size'] >= $max_file_size) {
                http_error('5MB 까지만 업로드 가능합니다.');
            }

            $timeNow = date("Y-m-d"); // 폴더명으로 사용할 현재 날짜
            $dir = "././public/upload/$timeNow"; // 폴더 위치, 이름
            $upload_dir = $dir.'/'; // 업로드 파일 저장 위치

            // 현재 날짜를 이름으로 가진 폴더 없을경우 생성
            if(is_dir($dir) != true) {
                mkdir($dir, 0700);
            }

            $userId = null;
            $lti = null;
            $fileName = rand_string(); // 업로드될 파일 명
            $path = $fileName.'.'.$ext;

            if(move_uploaded_file($file['tmp_name'], $upload_dir.$path)) {
                // echo '<a href="/public/upload">업로드 파일 목록</a>';
                http_header();
                $res = [
                    "result" => true,
                ];
                echo json_encode($res);
            }
        }
        else {
            http_error('파일이 업로드되지 않았습니다.');
        }

    }
    else
    {
        http_error(false);
    }
}

업로드된 파일의 유효성을 검사하고 레파토리에 업로드시키기까지의 과정을 순서대로 설명하자면

  1. 업로드된 데이터의 값과 이름이 있는지 검사한다
  2. 파일의 이름 값과 확장자를 반환받는다
  3. 지정한 확장자에 맞는 파일인지 검사한다
  4. 지정한 파일 크기를 초과하는 파일인지 검사한다
  5. 파일이 업로드된 시기를 기점으로 해당 날짜를 이름으로 가지는 업로드폴더에 있는지 검사하고 존재하지 않을 경우 새로 폴더를 생성한다.
  6. 위의 검사를 모두 통과했을 경우 지정된 폴더에 업로드 된 파일을 저장한다.
  7. 파일 저장이 성공했다면 reslut: true 라는 결과값을 반환한다.

실제 웹서버에 접속해 파일 업로드 기능을 사용해보면 아래와 같은 결과를 얻을 수 있다.

 

pulbic/upload/
public/upload/2020-12-04/

 

보기와 같이 업로드한 파일이 해당 날짜명으로 생성된 폴더 내에 난수값을 이름으로 가진채로 저장된것을 볼 수 있다.

실제 서비스에서 파일 업로드를 구현해야 할 경우 S3 클라우드 연동, 트래픽 관리, 파일 목록 테이블등의 더욱 복잡한 기능들이 동반되어야 하겠지만 이번 글에서는 로컬 환경에서 파일 업로드를 하는 경우에 한해서만 코드를 작성해보았다. 다음번에 기회가 된다면 실무에서 사용되는 파일 업로드 파이프라인에 대해 기고해보자 한다.

'개발 > 백엔드' 카테고리의 다른 글

Codeigniter 4에서 바뀐 것들  (0) 2020.11.16
PHP&Codeigniter 게시판 예제  (0) 2020.01.31