• wp_handle_upload()はアップロード結果をfile、url、typeまたはerrorで確認する

wp_handle_upload()はアップロード結果をfile、url、typeまたはerrorで確認する

公開日: 執筆:佐藤

wp_handle_upload()を使うときは、$_FILESの一要素を変数へ取り出して渡します。成功時のfile、url、typeと、失敗時のerrorを分け、errorがないときだけ次の処理へ進みます。

この関数は、ファイル名、拡張子とMIMEタイプ、ファイルサイズ、PHPによるアップロードかどうかを調べ、WordPressのアップロード先へファイルを移します。実行者の権限、フォームのnonce、入力を受け付ける目的までは、呼出側で確認してください。

wp_handle_upload()には一つのファイルを変数で渡す

WordPress 3.9.1の公式Coreでは、wp_handle_upload()の第一引数は、$_FILESに入った一ファイル分の配列です。参照渡しなので、配列要素を変数へ取り出してから渡します。

$uploaded_file = $_FILES['satolab_document'];
$result = wp_handle_upload( $uploaded_file );

複数ファイルを受け取る場合も、関数を一回だけ呼んで全件を任せるのではなく、一ファイルずつ同じ形へそろえて呼びます。

wp_handle_upload()はwp-admin/includes/file.phpで定義されています。管理画面以外の処理から使う場合は、関数が読み込まれているか確認し、必要なときだけファイルを読み込みます。

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

権限とnonceを確認してからアップロードを処理する

独自フォームでは、ファイルを移す前に、実行者と送信元を確認します。次は、管理者向けの独自処理を説明するための例です。フォーム側には、同じactionを持つnonceと、actionのhidden項目があるものとします。

if ( ! current_user_can( 'upload_files' ) ) {
    wp_die( 'アップロード権限がありません。' );
}

check_admin_referer( 'satolab_upload_document' );

if ( empty( $_FILES['satolab_document'] ) ) {
    wp_die( 'ファイルが選択されていません。' );
}

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

$uploaded_file = $_FILES['satolab_document'];
$overrides = array(
    'action' => 'satolab_upload_document',
);

$result = wp_handle_upload( $uploaded_file, $overrides );

actionを上書きすると、関数は$_POST['action']とその値を照合します。この検査はnonceの代わりではありません。権限、nonce、フォームactionは、それぞれ別に確認します。

拡張子とMIMEタイプの検査を無効にしない

WordPress 3.9.1のwp_handle_upload()は、wp_check_filetype_and_ext()を使ってファイル名の拡張子とMIMEタイプを調べます。許可された種類として確認できず、実行者がunfiltered_upload権限を持たない場合は、アップロードを失敗として返します。

$overridesでは検査を変更できますが、独自フォームだからという理由でtest_type、test_size、test_uploadを一括して無効にしてはいけません。フォームactionの調整と、ファイルが空でないか、PHPによるアップロードか、種類が許可されているかの検査は別です。

受け付ける種類を限定するなら、用途から先に決めます。たとえば、社内で確認するPDFだけを受け取る処理と、公開画像を受け取る処理では、許可するMIMEタイプも、公開後の扱いも違います。

返り値は真偽ではなくerrorの有無で分ける

成功すると、wp_handle_upload()は三つの値を持つ配列を返します。

キー 内容
file サーバー内で移動後のファイルパス
url アップロードされたファイルへ到達するURL
type 確認されたMIMEタイプ

失敗すると、標準のエラー処理はerrorを持つ配列を返します。失敗時も配列なので、if ( $result )だけでは成功と失敗を分けられません。

if ( isset( $result['error'] ) ) {
    wp_die( esc_html( $result['error'] ) );
}

$file_path = $result['file'];
$file_url  = $result['url'];
$file_type = $result['type'];

確認記録には、元のファイル名、返されたMIMEタイプ、保存先、公開URL、処理担当、エラーの有無を残します。エラーメッセージを捨てて同じ処理を繰り返すと、サイズ、種類、保存先のどこで止まったかを判断できません。

ファイルの移動とメディアへの登録を分ける

wp_handle_upload()が成功すると、ファイルはアップロード先へ移動します。しかし、この処理だけでは、WordPressの投稿として添付ファイルを作りません。

メディア画面で管理する必要があるなら、返されたファイル情報を確認したあと、添付ファイル投稿の登録とメタデータ作成を別に設計します。ファイルが移動したこと、添付ファイル投稿が作られたこと、記事へ表示されたことを、一つの成功判定へまとめないでください。

最初の一手は、独自フォームの権限、nonce、actionを確認し、一つの小さな許可済みファイルで返り値を記録することです。file、url、typeまたはerrorを見てから、メディア登録や公開処理を加えてください。

戻る