web-dev-qa-db-ja.com

WP Rest API - 添付ファイルを保存せずにメディアをアップロードする

ファイルがサーバーにアップロードされた後にフックし、ファイルパスを取得してから、WordPressが添付ファイルの投稿を保存しないようにする必要があります。

私はこのフィルタadd_filter('attachment_fields_to_save', 'attachment_stuff');を見つけましたが、これは添付ファイル投稿が作成された後です、私は投稿保存の前にフックしたいです。

更新26.03.2018

添付ファイルを保存せずにファイルを保存するために、カスタムメディアエンドポイントを使用しました。以下の完全な例は answer にあります

3
BenB

あなたのコメントに基づいて、あなたはREST AP​​Iを使っているようです。ファイルをアップロードしてからAPIエンドポイントでこの目的に使用できる添付ファイルの投稿を作成するまでの間に、フックはありません。

あなたができる最善のことはrest_insert_attachmentアクションを使うことであるようです。添付ファイルポストのWP_Postオブジェクトとリクエストを表すWP_REST_Requestオブジェクトを持つコールバック関数を提供します。このアクションは、添付ファイルの投稿が作成された直後、ただしメタデータまたはサイズが生成される前に呼び出されます。ですから、ここにフックして、投稿として保存してはいけないメディアを特定するために使用しているフラグのリクエストを確認し、パスを取得してから添付の投稿を削除します。

function wpse_297026_rest_insert_attachment( $attachment, $request, $creating ) {
    // Only handle new attachments.
    if ( ! $creating ) {
        return;
    }

    // Check for parameter on request that tells us not to create an attachment post.
    if ( $request->get_param( 'flag' ) == true ) {
        // Get file path.
        $file = get_attached_file( $attachment->ID );

        // Do whatever you need to with the file path.

        // Delete attachment post.
        wp_delete_post( $attachment->ID );

        // Kill the request and send a 201 response.
        wp_die('', '', 201);
    }
}
add_action( 'rest_insert_attachment', 'wpse_297026_rest_insert_attachment' )

添付ファイルを作成していないのであれば、添付ファイルエンドポイントを使用しないでください。そのため、このコードでは厄介にリクエストを強制終了しなければなりません。 rest_insert_attachmentの後に続くものはすべて、添付ファイルポストの存在を前提としており、そのエンドポイントのコントローラー用のコードの大部分は、添付ファイルポストに対してのみ意味のあるデータの作成と管理専用です。あなたはおそらくこの種の作業のためにあなた自身のエンドポイントを作成するべきです。

3
Jacob Peattie

ファイルをアップロードして添付ファイルを作成することは、 media_handle_upload 関数によって処理されます。あなたがソースから見ることができるように、それは最初にファイルをアップロードし、次にメタデータ(オーディオファイルのためのいくつかの長いものを含む)を集め始め、そして添付ファイルポストを作成するために wp_insert_attachment を呼び出します。あなたが引っ掛かることができる場所はありません。

後者の関数は、 wp_insert_post の単なるプレースホルダーです。ここには、メタデータをフィルタリングするためのフックがたくさんあります。ただし、投稿が作成されるのを妨げる条件が1つだけあります。そこにはif ( ! empty( $import_id ) )があります。そして$import_idを台無しにする明白な方法はありません。だから、あなたは立ち往生しています。

関数の少し後の部分にdo_action( 'add_attachment', $post_ID );という呼び出しがあります。添付ファイルの投稿が作成された直後に発生します。あなたはすぐに再び投稿を削除するためにこれを使うことができます:

add_action ('add_attachment', 'wpse297026_delete_post');
function wpse297026_delete_post ($post_ID) {
  wp_delete_post ($post_ID);
  }

これはアップロードされたファイルをその場所に残しますが、WordPressはそれを見失ってしまいます。

2
cjbj

ポストパートを保存せずに、カスタムエンドポイントでwpメディアエンドポイントからのコードを使用することになりました。

誰かがこれを必要とする場合に備えて、これは27人の子供のテーマに関する完全な例です。

  1. これをfunctions.phpに追加してください。

    $Custom_Media_Uploader = new Custom_Media_Uploader();
    $Custom_Media_Uploader->init();
    
    class Custom_Media_Uploader {
    
      function init() {
        add_action( 'rest_api_init', [ $this, 'register_routes' ] );
    
      }
    
    
      function register_routes() {
        $version   = '1';
        $namespace = 'custom-end-point/v' . $version;
        $base      = 'media';
        register_rest_route( $namespace, '/' . $base, array(
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [ $this, 'upload_file' ],
                'permission_callback' => [ $this, 'file_upload_permissions' 
             ],
                'args'                => [],
            ]
        ) );
    }
    
      function file_upload_permissions() {
        return is_user_logged_in();
      }
    
      function upload_file( $request ) {
        $params = $request->get_params();
    
        if ( ! empty( $request['post'] ) && in_array( get_post_type( $request['post'] ), array(
                'revision',
                'attachment'
            ), true )
        ) {
            return new WP_Error( 'rest_invalid_param', __( 'Invalid parent type.' ), array( 'status' => 400 ) );
        }
      // Get the file via $_FILES or raw data.
        $files   = $request->get_file_params();
        $headers = $request->get_headers();
        if ( ! empty( $files ) ) {
            $file = $this->upload_from_file( $files, $headers );
        } else {
            $file = $this->upload_from_data( $request->get_body(), $headers );
        }
        if ( is_wp_error( $file ) ) {
            return $file;
        }
        $name       = basename( $file['file'] );
        $name_parts = pathinfo( $name );
        $name       = trim( substr( $name, 0, - ( 1 + strlen( $name_parts['extension'] ) ) ) );
        $url        = $file['url'];
        $type       = $file['type'];
        $file       = $file['file'];
    
        return [ 'url' => $url, 'type' => $type ];
      }
    
    
    /**
     * Handles an upload via multipart/form-data ($_FILES).
     *
     * @since 4.7.0
     *
     * @param array $files Data from the `$_FILES` superglobal.
     * @param array $headers HTTP headers from the request.
     *
     * @return array|WP_Error Data from wp_handle_upload().
     */
      protected function upload_from_file( $files, $headers ) {
    
        if ( empty( $files ) ) {
            return new WP_Error( 'rest_upload_no_data', __( 'No data supplied.' ), array( 'status' => 400 ) );
        }
    // Verify hash, if given.
        if ( ! empty( $headers['content_md5'] ) ) {
            $content_md5 = array_shift( $headers['content_md5'] );
            $expected    = trim( $content_md5 );
            $actual      = md5_file( $files['file']['tmp_name'] );
            if ( $expected !== $actual ) {
                return new WP_Error( 'rest_upload_hash_mismatch', __( 'Content hash did not match expected.' ), array( 'status' => 412 ) );
            }
        }
      // Pass off to WP to handle the actual upload.
        $overrides = array(
            'test_form' => false,
        );
     // Bypasses is_uploaded_file() when running unit tests.
        if ( defined( 'DIR_TESTDATA' ) && DIR_TESTDATA ) {
            $overrides['action'] = 'wp_handle_mock_upload';
        }
        /** Include admin functions to get access to wp_handle_upload() */
        require_once ABSPATH . 'wp-admin/includes/admin.php';
        $file = wp_handle_upload( $files['file'], $overrides );
        if ( isset( $file['error'] ) ) {
            return new WP_Error( 'rest_upload_unknown_error', $file['error'], array( 'status' => 500 ) );
        }
    
        return $file;
      }
    }
    
  1. page-upload.phpという名前でテーマのルートにファイルを作成します。

    <?php get_header(); ?>
         <div class="wrap">
         <div id="primary" class="content-area">
          <main id="main" class="site-main" role="main">
            <input type='file' onchange="uploadFile(this);"/>
            <div style="display:none" id="ajax-response">
                <div><b>File URL: </b><span id="file-url"></span></div>
                <div><b>File type: </b><span id="file-type"></span></div>
                <div></div>
            </div>
        </main><!-- #main -->
      </div><!-- #primary -->
    </div><!-- .wrap -->
    
    <script>
    function uploadFile(input) {
        if (input.files && input.files[0]) {
            var file = input.files[0];
            var formData = new FormData();
            formData.append('file', file);
    
            // Fire the request.
            jQuery.ajax({
                url: '<?php echo esc_url_raw( rest_url() ) ?>custom-end-point/v1/media',
                method: 'POST',
                processData: false,
                contentType: false,
                beforeSend: function (xhr) {
                    xhr.setRequestHeader('X-WP-Nonce', '<?php echo wp_create_nonce( 'wp_rest' ) ?>');
                },
                data: formData
            }).success(function (response) {
                jQuery('#file-url').text(response.url);
                jQuery('#file-type').text(response.type);
                jQuery('#ajax-response').show();
                console.log(response);
            }).error(function (response) {
                console.log(response);
            });
    
        }
    }
    </script>
    
    <?php get_footer();
    
  2. 「upload」というタイトルのページを作成して保存し、www.domain.com/uploadに移動してファイルをアップロードすると、ファイルのアップロード後にメディアエンドポイントから返されたURLとファイルタイプを確認できます。

あなたがログインし、パーマリンクがpost-nameに設定されていることを確認して、エンドポイントが機能できるようにします。

1
BenB