web-dev-qa-db-de.com

WP Rest API - Laden Sie Medien hoch, ohne den Anhang zu speichern

Ich muss nach dem Hochladen der Datei auf den Server einen Hook ausführen, den Dateipfad ermitteln und dann verhindern, dass WordPress den Anhangbeitrag speichert.

Ich habe diesen Filter add_filter('attachment_fields_to_save', 'attachment_stuff'); gefunden, aber nachdem der Anhang erstellt wurde, möchte ich ihn vor dem Speichern des Beitrags einbinden.

Update 26.03.2018

Am Ende habe ich einen benutzerdefinierten Medienendpunkt verwendet, um die Dateien zu speichern, ohne einen Anhang zu speichern. Vollständiges Beispiel unten in Antwort

3
BenB

Aufgrund Ihres Kommentars scheinen Sie die REST -API zu verwenden. Es gibt keinen Haken zwischen dem Hochladen der Datei und dem Erstellen des Anhangposts, der für diesen Zweck auf dem API-Endpunkt verwendet werden könnte.

Das Beste, was Sie tun können, scheint die Aktion rest_insert_attachment zu sein. Es bietet Rückruffunktionen mit dem Objekt WP_Post für den Anhangsposten und dem Objekt WP_REST_Request, das die Anforderung darstellt. Diese Aktion wird unmittelbar nach dem Erstellen des Anhangposts, jedoch vor dem Generieren von Metadaten oder Größen aufgerufen. Sie können sich also hier anmelden, die Anfrage nach dem von Ihnen verwendeten Flag überprüfen, um Medien zu identifizieren, die nicht als Beitrag gespeichert werden sollen, den Pfad abrufen und dann den Anhangsbeitrag löschen.

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' )

Ich denke, es muss darauf hingewiesen werden, dass Sie den Endpunkt für Anhänge nicht verwenden sollten, wenn Sie keine Anhänge erstellen. Aus diesem Grund müssen wir die Anfrage in diesem Code umständlich beenden. Alles nach rest_insert_attachment setzt das Vorhandensein eines Anhangposts voraus und der größte Teil des Codes für den Controller für diesen Endpunkt dient der Erstellung und Verwaltung von Daten, die nur für einen Anhangpost sinnvoll sind. Sie sollten wahrscheinlich einen eigenen Endpunkt für diese Art von Arbeit erstellen.

3
Jacob Peattie

Das Hochladen der Datei und das Anlegen eines Anhangs erfolgt über die Funktion media_handle_upload . Wie Sie aus der Quelle ersehen können, lädt es zuerst die Datei hoch, beginnt dann mit dem Sammeln von Metadaten (einschließlich einiger langwieriger Dinge für Audiodateien) und ruft dann wp_insert_attachment auf, um den Anhangspost zu erstellen. Es gibt keinen Ort, an dem Sie sich einklinken können.

Die letztere Funktion ist nur ein Platzhalter für wp_insert_post . Hier haben Sie eine Menge Haken, um Metadaten zu filtern. Es gibt jedoch nur eine Bedingung, die verhindert, dass der Beitrag erstellt wird. Dort steht if ( ! empty( $import_id ) ). Und es gibt keine offensichtliche Möglichkeit, sich mit $import_id herumzuschlagen. Also steckst du fest.

Außer, dass etwas später in der Funktion dieser Aufruf erscheint: do_action( 'add_attachment', $post_ID );. Dies wird unmittelbar nach dem Erstellen eines Anhangposts ausgelöst. Sie können dies verwenden, um den Beitrag sofort wieder zu löschen:

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

Dadurch bleibt die hochgeladene Datei an ihrem Platz, WordPress hat jedoch den Überblick verloren.

2
cjbj

Am Ende habe ich den Code vom wp media-Endpunkt in einem benutzerdefinierten Endpunkt verwendet, ohne den Beitragsteil zu speichern.

Hier ist ein vollständiges Beispiel für ein Thema mit 21 Kindern, falls jemand dies benötigt.

  1. Fügen Sie dies zu functions.php hinzu

    $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. erstellen Sie eine Datei im Stammverzeichnis des Themas mit dem Namen 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. Erstellen und speichern Sie eine Seite mit dem Titel "Upload" und navigieren Sie zu www.domain.com/upload, laden Sie eine Datei hoch. Nach dem Hochladen einer Datei können Sie die zurückgegebene URL und den zurückgegebenen Dateityp vom Medienendpunkt anzeigen.

Stellen Sie sicher, dass Sie angemeldet sind und die Permalinks auf Post-Name eingestellt sind, damit der Endpunkt funktioniert.

1
BenB