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_Filesystem
y wp_insert_attachment()
correcto? ¿O debería encontrar alguna forma de usar media_handle_upload()
en su lugar?
¡Gracias!
plugin-development
ajax
uploads
media
aendrew
fuente
fuente
media_handle_upload()
requieren una identificación de publicación, y su "amigo"wp_handle_upload()
requiere que exista un archivo en la$_FILES
matriz, 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 enwp_upload_bits
lugar de tratar con el sistema de archivos WP. Además,wpcom_vip_file_get_contents
haga que su código solo esté disponible en un concurso VIP, si necesita un enfoque más general, un estándarfile_get_contents
debería estar bien, y si necesita almacenar en caché, entonces un transitorio debería ser el truco.wp_upload_bits
, eso es muy útil. ¡Gracias!Respuestas:
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:
theme / js / js-plugin-name.js:
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:
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 )
fuente