WP REST API-上传媒体而不保存附件帖子

时间:2018-03-16 作者:BenB

我需要在文件上传到服务器后挂接,获取文件路径,然后阻止WordPress保存附件帖子。

我找到了这个过滤器add_filter(\'attachment_fields_to_save\', \'attachment_stuff\'); 但这是在附件帖子创建之后,我想在帖子保存之前挂钩。

Update 26.03.2018

我最终使用自定义媒体端点来保存文件,而不保存附件帖子。下面的完整示例answer

3 个回复
最合适的回答,由SO网友:Jacob Peattie 整理而成

根据您的评论,您似乎正在使用REST API。上载文件和创建可在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 假设存在一个附件帖子,并且该端点的控制器的大部分代码专用于创建和管理仅对附件帖子有意义的数据。您可能应该为这类工作创建自己的端点。

SO网友:cjbj

上载文件并为其创建附件由函数处理media_handle_upload. 从源代码中可以看到,它首先上载文件,然后开始收集元数据(包括音频文件的一些冗长内容),然后调用wp_insert_attachment 创建附件帖子。没有一个地方你可以进去。

后一个函数只是wp_insert_post. 这里有很多钩子来过滤元数据。然而,只有一个条件阻止创建帖子,即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将无法跟踪它。

SO网友:BenB

我最终在自定义端点中使用了来自wp media端点的代码,而没有保存post部分。

以下是关于2017年儿童主题的完整示例,以防有人需要。

将此添加到函数中。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;
  }
}

在主题的根目录下创建一个名为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();
创建并保存标题为“upload”的页面,然后导航到www.domain。com/upload,上传文件,您可以在上传文件后从媒体端点查看返回的URL和文件类型。

确保您已登录,并且将永久链接设置为post name,以允许端点正常工作。

结束