워드프레스에서 파일 업로드 처리하기

이 글은 얼마 전 한국워드프레스사용자모임 Q&A 게시판에 올린 답글에 대한 보충입니다.

워드프레스에서 파일을 업로드하려면 어떻게 할까요? 너무 막연한 질문인가요?

더 중요한 것은 왜 파일 업로드가 필요한지 그 용도를 따져보는 거겠죠. 사진이나 이미지 파일을 올려 이미지 갤러리를 만들려 할 수도 있고 XML이나 CSV 파일을 받아 어드민에서 처리하고 싶을 경우도 있을 것입니다. 용도는 다양하고 용도에 따라 처리 방법이 조금씩 다를 수 있습니다.

하지만 어떤 용도건 파일 업로드 방법 자체는 다르지 않습니다. 웹 브라우저에서 파일을 업로드하는 방법은 이미 정해져 있기 때문에 워드프레스라 해서 크게 다를 건 없죠. 브라우저에서 입력폼을 통해 업로드할 파일을 입력받은 다음 서버측에서 받아 적절한 처리를 해주면 됩니다.

서버측 처리도 마찬가지입니다. 워드프레스는 PHP 기반이니 PHP 파일 업로드 방법에 따라 처리하면 됩니다. 다만 워드프레스는 업로드된 파일 처리를 좀 더 쉽게 할 수 있도록 몇몇 도움 함수를 제공합니다. 대표적인 함수가 wp_handle_upload 함수죠.

그럼 간단하게 테스트를 해 보죠. 페이지를 하나 만들고 페이지 내에서 파일을 업로드하여 업로드된 파일이 워드프레스의 업로드 디렉터리 내에 저장되도록 해 보겠습니다.

파일 업로드 폼 페이지 만들기

우선 업로드 폼을 만들 페이지 템플릿을 하나 추가합니다. 템플릿 파일명은 임의로 주면 되지만, 여기서는 page-upload-demo.php 라고 주겠습니다. 이 파일을 사용 중인 테마의 루트 폴더에 만들어 올리고 워드프레스 관리자 화면에서 “새 페이지 추가”를 하여 새로 추가된 페이지의 고유주소(permalink)값을 upload-demo로 맞추면 되겠죠.

그런 다음 편집기를 열어 방금 생성한 페이지 템플릿 속에 업로드 입력 양식 코드를 다음과 같이 추가합니다.

<?php
get_header(); ?>

<form method="post" enctype="multipart/form-data">
    <p>
        <label for="title">제목: </label>
        <input type="text" id="title" name="title">
    </p>
    <p>
        <label for="image">사진: </label>
        <input type="file" name="image">
    </p>
    <p>
        <input type="submit" value="업로드">
    </p>
</form>    

<?php get_footer(); ?>

그러면 다음과 같이 업로드 페이지가 표시될 것입니다. (모양은 사용하는 테마에 따라 다를 수 있습니다)


업로드 파일 받기

입력 폼을 만들었다면 이제 입력값을 받아 처리할 차례겠죠. 그런데 입력값을 받아 처리하는 것은 어디서 하면 좋을까요? 여기서는 앞서 <form> 태그를 만들 때 별도의 action 값을 지정하지 않았기 때문에 입력 폼과 동일한 파일, 즉 page-upload-demo.php 파일로 웹요청이 가게 되고 따라서 이 파일에서 업로드 처리를 하도록 하겠습니다.

앞서 만든 템플릿 파일 page-upload-demo.php 의 상단에 업로드 파일을 받아서 처리하는 부분을 다음과 같이 추가합니다.

<?php

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    
    $file_name = $_FILES['image']['name'];
    $file_tmp = $_FILES['image']['tmp_name'];
    $upload_dir = wp_upload_dir();
    
    if (is_uploaded_file($file_tmp)) {
        move_uploaded_file($file_tmp, $upload_dir['path']. "/". $file_name);
        echo "File ". $file_name ." uploaded successfully.\n";
    }

get_header(); ?>

이제 페이지에서 파일을 하나 선택해 업로드해 보면 워드프레스의 업로드 디렉터리(wp-content\uploads\ 아래에 방금 업로드한 파일이 놓여 있는 것을 확인할 수 있을 것입니다.


wp_handle_upload

방금 만든 업로드 처리 부분은 실은 통상적인 PHP의 파일 업로드 API를 사용한 방법입니다. 워드프레스에서는 앞서 만든 파일 업로드 처리 부분을 좀 더 간편하게 처리할 수 있는 몇몇 도움 함수를 제공하는데 그 중 대표적인 것이 wp_handle_upload 함수입니다.

wp_handle_upload 함수를 사용하면 앞서 작성한 업로드 코드를 다음과 같이 좀 더 간단하게(?) 만들 수 있습니다.

<?php

if ( ! function_exists( 'wp_handle_upload' ) ) {
    require_once( ABSPATH . 'wp-admin/includes/file.php' );
}

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    
    $uploadedfile = $_FILES['image'];
    $upload_overrides = array( 'test_form' => false );
    $movefile = wp_handle_upload( $uploadedfile, $upload_overrides );
    var_dump( $movefile );
    
}

get_header(); ?>

admin-post로 업로드 처리

앞서는 파일 업로드 처리 루틴을 입력 폼과 동일한 템플릿 파일 내에서 처리했지만, 실은 이 방법은 코드가 복잡해 지면 관리하기가 어려운 단점이 있습니다. 어딘가 한 곳을 정해서 그 곳에서 웹요청을 일괄되게 처리하는 게 좀 더 나은 방법입니다.

이를 위해 워드프레스에서는 웹 요청 처리를 위한 핸들링 방식을 별도로 제공합니다. 방법은 간단합니다. 워드프레스에서 발생하는 모든 웹요청의 종단점(endpoint)을 워드프레스가 지정한 한 지점으로 맞추고 그 곳에서 모든 것을 해결하는 방식입니다.

이를 위해 앞서 만든 업로드 폼 코드 부분을 다음과 같이 변경합니다. 폼의 action 값을 워드프레스의 admin-post.php 로 맞추고 아래에 히든(hidden) 필드를 하나 추가했습니다.

<form action="<?php echo admin_url('admin-post.php'); ?>" method="post" enctype="multipart/form-data">
    <input type="hidden" name="action" value="user_form">
    <p>
        <label for="title">제목: </label>
        <input type="text" id="title" name="title">
    </p>
    <p>
        <label for="image">사진: </label>
        <input type="file" name="image">
    </p>
    <p>
        <input type="submit" value="업로드">
    </p>
</form>    

이제 이 업로드 요청은 어디에서 처리할까요? 테마 속 functions.php 파일 내에서 처리해도 되고 간단하게 플러그인을 하나 만들어도 되겠죠.

여기서는 간단하게 테마의 functions.php 파일 내에서 처리하겠습니다. admin_post_user_form 액션을 후킹하는 방식입니다.

add_action( 'admin_post_user_form', 'demo_process_user_form' );

function demo_process_user_form() {

    if ( ! function_exists( 'wp_handle_upload' ) ) {
        require_once( ABSPATH . 'wp-admin/includes/file.php' );
    }
    
    $uploadedfile = $_FILES['image'];
    $upload_overrides = array( 'test_form' => false );
    $movefile = wp_handle_upload( $uploadedfile, $upload_overrides );
    // var_dump( $movefile );
    // redirect back
    wp_safe_redirect( wp_get_referer() );
    exit;
}

이 부분은 이미 다른 글에서 자세하게 다루고 있으니 자세한 설명은 생략합니다. 필요한 분들은 아래 글을 참고 바랍니다.

워드프레스에서 웹 요청 처리하기

사실 워드프레스에서 사용자가 직접 업로드를 처리할 일은 거의 없습니다. 간혹 있다 하더라도 이미 워드프레스 플러그인들 중에 업로드와 관련된 플러그인들이 다양한 용도에 맞춰 나와 있기 때문에 직접 이렇게 코드를 처리할 일은 아마도 없을 것입니다. 이 방법은 그저 워드프레스에서 업로드 처리를 어떻게 하는지 공부하는 용도로만 사용하면 좋을 듯 싶네요. 🙂

0 thoughts on “워드프레스에서 파일 업로드 처리하기”