J'ai un plugin TinyMCE qui génère des images PNG à l'aide de HTMLCanvasElement.toDataURL()
( MDN ). Actuellement, je les affiche simplement sur le backend en mettant l'URI de données dans une balise d'image, mais j'aimerais vraiment les ajouter à la bibliothèque multimédia WordPress.
Quelle est la meilleure façon (c'est-à-dire compatible VIP) de télécharger des images actuellement sérialisées en tant qu'URI de données encodées en base64?
Voici ma fonction de téléchargement jusqu'à présent:
<?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();
}
}
Est-ce que j'utilise WP_Filesystem
et wp_insert_attachment()
corrige? Ou devrais-je trouver un moyen d'utiliser à la media_handle_upload()
place?
Merci!
plugin-development
ajax
uploads
media
aendrew
la source
la source
media_handle_upload()
nécessitent un identifiant de publication, et son "ami"wp_handle_upload()
nécessite qu'un fichier existe dans le$_FILES
tableau, donc je pense vraiment qu'ils ne correspondent pas à vos besoins. À mon humble avis, vous pouvez utiliser votre approche actuelle, probablement que j'avais utiliséewp_upload_bits
au lieu de traiter avec le système de fichiers WP. De plus,wpcom_vip_file_get_contents
rendez votre code uniquement disponible dans le concours VIP, si vous avez besoin d'une approche plus générale, un standardfile_get_contents
devrait convenir, et si vous devez mettre en cache, un transitoire devrait faire l'affaire.wp_upload_bits
- c'est super utile. Merci!Réponses:
Dans un plugin tinymce précédent, j'ai créé - J'ai configuré un transport ajax personnalisé afin que je puisse simplement utiliser le blob directement à partir de l'image src d'une image distante au lieu de base64 sur un attribut de données, puis j'ai utilisé l'API REST pour télécharger l'image vers la médiathèque de js.
Base64 sera environ 35% plus grand qu'un blob, donc s'il y a beaucoup de graphiques ou de téléchargements, cela contribuera à réduire considérablement la bande passante de téléchargement, même avec une seule image, les performances doivent être prises en compte car de nombreux utilisateurs ont tendance à avoir une tonne de plugins installés. Vous savez probablement déjà à quel point l'éditeur et tinymce peuvent être gourmands en ressources.
De plus, dans l'ensemble, je déteste sortir de JS en PHP quand ce n'est pas nécessaire à 100%: P
Puisque vous avez déjà l'ensemble de données dans base64 - vous pouvez utiliser un simple convertisseur - il y en a beaucoup là-bas, je viens de copier et coller celui que j'ai trouvé pour l'exemple ci-dessous. https://www.npmjs.com/package/base64toblob fonctionne bien si vous vouliez quelque chose de rapide à intégrer dans votre build.
Voici un exemple de travail rapide utilisant une image d'espace réservé base64, je viens de le jeter dans un thème pour les tests, mais vous pouvez l'utiliser où vous le souhaitez:
theme / functions.php:
theme / js / js-plugin-name.js:
Le fichier sera incrémenté -1, -2 automatiquement comme d'habitude afin que vous n'écrasiez pas yadda yadda, et la réponse contiendra l'objet multimédia avec tout ce dont vous avez besoin.
certains des paramètres utiles en réponse:
Si vous avez converti en base64, vous pouvez également écrire un transport ajax personnalisé jquery et saisir l'img src et ignorer tout le décodage base64 pour blober également, et cela devrait aider les résultats de performance de l'encodage juste à décoder, etc.
ÉDITER:
J'ai oublié de mentionner: l'API REST est disponible pour n'importe quel site vip, donc ça devrait aller. Je suppose que vous générez les graphiques dans l'éditeur tinymce à l'arrière - de sorte que l'utilisateur est déjà authentifié. L'exemple ci-dessus passe simplement le nonce dans les en-têtes dans une demande ajax, ce qui est une exigence de sécurité sur vip.
Vous pouvez vous référer à la documentation pour la conformité ici: https://vip.wordpress.com/documentation/api/
De plus, je n'ai pas remarqué que vous utilisiez HTMLCanvasElement.toDataURL ()! - Vous pouvez simplement ignorer le décodage de b64 et obtenir le blob directement car vous ne récupérez pas l'image à partir d'une télécommande et essayez de l'ajouter et d'utiliser HTMLCanvasElement.toBlob () ( MDN )
la source