Guardar datos-URI en la biblioteca de medios

9

Tengo un complemento TinyMCE que genera imágenes PNG usando HTMLCanvasElement.toDataURL()( MDN ). Actualmente, solo los estoy mostrando en el backend colocando el URI de datos en una etiqueta de imagen, pero realmente me gustaría agregarlos a la Biblioteca de medios de WordPress.

¿Cuál es la mejor manera (es decir, compatible con VIP) de cargar imágenes actualmente serializadas como un URI de datos codificado en base64?

Aquí está mi función de carga hasta ahora:

<?php

/**
 * AJAX callback that inserts chart as attachment into the WP database
 */
public static function insert_axis_attachment() {
    // Get config
    $axis_config = json_decode( $_POST['axisConfig'] );

    if ( ! isset( $_POST['axisJS_nonce'] )
        || ! wp_verify_nonce( $_POST['axisJS_nonce'] )
        || ! current_user_can( 'upload_files' )
        || ! current_user_can( 'edit_post', $_POST['post_id'] )
        || ( isset( $axis_config->ID ) && ! current_user_can( 'edit_post', $axis_config->ID ) )
    ) {
        return false;
    }

    // Begin saving PNG to filesystem
    if ( false === ( $creds = request_filesystem_credentials( 'admin-ajax.php', '', false, false, null ) ) ) {
        return false; // stop processing here
    }
    if ( ! WP_Filesystem( $creds ) ) {
        request_filesystem_credentials( 'admin-ajax.php', '', true, false, null );
        return false;
    }
    global $wp_filesystem;
    $upload_dir = wp_upload_dir();
    $chart_filename = sanitize_title_with_dashes( $axis_config->chartTitle ) . '_' . time() . '.png';
    $filename = trailingslashit( $upload_dir['path'] ) . $chart_filename;
    $uriPhp = 'data://' . substr( $_POST['axisChart'], 5 ); // Via http://stackoverflow.com/questions/6735414/php-data-uri-to-file/6735458#6735458
    $binary = wpcom_vip_file_get_contents( $uriPhp );
    $wp_filesystem->put_contents(
        $filename,
        $binary,
        FS_CHMOD_FILE // predefined mode settings for WP files
    );

    // Insert or update attachment.
    if ( ! $axis_config->ID ) {
        $attachment = array(
            'guid' => $upload_dir['url'] . '/' . basename( $filename ),
            'post_title' => $axis_config->chartTitle,
            'post_content' => '', // Must be empty string
            'post_status' => 'published',
            'post_mime_type' => 'image/png',
            'post_status' => 'inherit',
        );

        $attach_id = wp_insert_attachment( $attachment, $filename, $_POST['post_id'] );

        // Make sure that this file is included, as wp_generate_attachment_metadata() depends on it.
        require_once( ABSPATH . 'wp-admin/includes/image.php' );

        // Generate the metadata for the attachment, and update the database record.
        $attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
        wp_update_attachment_metadata( $attach_id, $attach_data );
        update_post_meta( $attach_id, '_axisWP', $axis_config );
        echo esc_attr( $attach_id );
        die();
    } else {
        update_attached_file( $axis_config->ID, $filename );
        update_post_meta( $axis_config->ID, '_axisWP', $axis_config );
        echo esc_attr( $axis_config->ID );
        die();
    }
}

¿Cómo estoy usando WP_Filesystemy wp_insert_attachment()correcto? ¿O debería encontrar alguna forma de usar media_handle_upload()en su lugar?

¡Gracias!

aendrew
fuente
No estoy seguro de que este sea un buen lugar para preguntar en el contexto del cumplimiento de VIP. Aquí hay muy pocas preguntas al respecto y no estoy seguro de que haya personas con experiencia tan específica dando vueltas. : \
Rarst
1
@rarst Ni siquiera estoy buscando cumplimiento VIP tanto como "Estoy usando las clases de manejo de archivos de WordPress correctamente", en la forma de 12 factores VIP lo hace (es decir, si alguien tiene una "carga automática de todos los medios complemento de imágenes de la biblioteca a Amazon S3 ", funcionará con eso también. Lo anterior parece funcionar (actualizando con los cambios ahora), simplemente no estoy seguro de que esté enganchado a la Biblioteca de Medios de manera convencional.
aendrew
1
media_handle_upload()requieren una identificación de publicación, y su "amigo" wp_handle_upload()requiere que exista un archivo en la $_FILESmatriz, por lo que realmente creo que no se ajustan a sus necesidades. En mi humilde opinión, puede utilizar su enfoque actual, probablemente lo he usado en wp_upload_bitslugar de tratar con el sistema de archivos WP. Además, wpcom_vip_file_get_contentshaga que su código solo esté disponible en un concurso VIP, si necesita un enfoque más general, un estándar file_get_contentsdebería estar bien, y si necesita almacenar en caché, entonces un transitorio debería ser el truco.
gmazzap
@GMI no sabía nada wp_upload_bits, eso es muy útil. ¡Gracias!
aendrew

Respuestas:

1

En un complemento de tinymce anterior que hice, configuré un transporte ajax personalizado para poder usar el blob directamente desde la imagen src de un img remoto en lugar de base64 en un atributo de datos, y luego usé la API REST para cargar la imagen a la mediateca en js.

Base64 será aproximadamente un 35% más grande que un blob, por lo que si hay muchos gráficos o cargas, esto ayudará a reducir bastante el ancho de banda de carga, incluso con una sola imagen, se debe considerar el rendimiento ya que muchos usuarios tienden a tener Una tonelada de complementos instalados. Probablemente ya sepa cuán intensivos en recursos pueden ser solo el editor y tinymce en primer lugar.

Además, en general odio salir de JS a PHP cuando no es 100% necesario: P

Dado que ya tiene el conjunto de datos en base64, podría usar un convertidor simple, hay muchos por ahí que acabo de copiar y pegar uno que encontré para el ejemplo a continuación. https://www.npmjs.com/package/base64toblob funciona bien si desea algo rápido para integrar en su compilación.

Aquí hay un ejemplo de trabajo rápido que utiliza datos de base64 de imagen de marcador de posición, lo acabo de incluir en un tema para probar, pero puede usarlo donde quiera:

tema / funciones.php:

    add_action( 'wp_enqueue_scripts', 'js_plugin_name_scripts' );

    function js_plugin_name_scripts() {
        wp_register_script( 'js-plugin-name', get_parent_theme_file_uri( 'js/js-plugin-name.js' ), array( 'wp-api' ) );
        wp_localize_script( 'wp-api', 'wpApiSettings', array(
            'root' => esc_url_raw( rest_url() ),
            'nonce' => wp_create_nonce( 'wp_rest' )
        ) );
        wp_enqueue_script( 'js-plugin-name' );
    }

theme / js / js-plugin-name.js:

    // Wait for API load.
    wp.api.loadPromise.done( function() {

        var base64, blob;

        /**
         * Convert base64 data to blob.
         * 
         * @param {string} base64
         * @param {string} mime 
         */
        function base64ToBlob( base64, mime ) {
            mime = mime || '';
            var sliceSize = 1024;
            var byteChars = window.atob( base64 );
            var byteArrays = [];

            for ( var offset = 0, len = byteChars.length; offset < len; offset += sliceSize ) {
                var slice = byteChars.slice( offset, offset + sliceSize );

                var byteNumbers = new Array( slice.length );
                for ( var i = 0; i < slice.length; i++ ) {
                    byteNumbers[i] = slice.charCodeAt(i);
                }

                var byteArray = new Uint8Array( byteNumbers );

                byteArrays.push( byteArray );
            }

            return new Blob(byteArrays, {type: mime});
        }

        base64 = "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";

        blob = base64ToBlob( base64, 'image/png' );

        // Upload to media library.
        jQuery.ajax( {
            url: wpApiSettings.root + 'wp/v2/media',
            method: 'POST',
            beforeSend: function ( xhr ) {
                xhr.setRequestHeader( 'X-WP-Nonce', wpApiSettings.nonce );
                xhr.setRequestHeader( 'Content-Disposition', 'attachment;filename=' + 'placeholder.png' );
            },
            data: blob,
            cache: false,
            contentType: false,
            processData: false
        } ).done( function ( response ) {

            // Response contains the media details.
            console.log( response );
        } );
    });

El archivo se incrementará -1, -2 automáticamente de la forma normal para que no sobrescriba cosas yadda yadda, y la respuesta contendrá el objeto multimedia con lo que necesite.

Algunos de los parámetros útiles en respuesta:

    response.id = post id
    response.source_url = url to file ie http://local.wordpress.dev/wp-content/uploads/2017/07/placeholder.png
    response.title.rendered(or .raw) = media title if needed
    response.slug = media slug
    response.media_details.height = contains the original uploaded img height
    response.media_details.width = contains the original uploaded img width
    response.media_details.sizes = contains the various img sizes generated - ie full/thumb/sm/med/lrg etc --- don't always rely on naming conventions ;)!

Si se convirtió a base64, entonces también podría escribir un transporte jquery ajax personalizado y tomar el img src y omitir hacer toda la decodificación base64 para cosas de blob, y debería ayudar a los éxitos de rendimiento de la codificación solo para decodificar, etc.

EDITAR:

Olvidé mencionar: la API REST está disponible para cualquier sitio vip, por lo que debería estar bien. Supongo que está generando los gráficos en el editor tinymce en el back-end, por lo que el usuario ya está autenticado. El ejemplo anterior es simplemente pasar el nonce a través de los encabezados en una solicitud ajax, que es un requisito de seguridad en vip.

Puede consultar la documentación para el cumplimiento aquí: https://vip.wordpress.com/documentation/api/

¡Tampoco me di cuenta de que estabas usando HTMLCanvasElement.toDataURL ()! - Puede omitir la decodificación de b64 y obtener el blob directamente ya que no está recuperando la imagen de un control remoto e intentando agregarla y usar HTMLCanvasElement.toBlob () ( MDN )

Tim Elsass
fuente
felicidades, primer uso útil del resto de la API que probablemente no sea trivial para replicar lo que veo
Mark Kaplun