Ich habe ein TinyMCE-Plugin , das PNG-Bilder mit HTMLCanvasElement.toDataURL()
( MDN ) generiert . Derzeit zeige ich sie nur im Backend an, indem ich den Daten-URI in ein Bild-Tag einfüge, aber ich möchte diese wirklich zur WordPress-Medienbibliothek hinzufügen.
Was ist die beste (dh VIP-konforme) Methode zum Hochladen von Bildern, die derzeit als base64-codierte Daten-URI serialisiert sind?
Hier ist meine Upload-Funktion bisher:
<?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();
}
}
Ist wie ich benutze WP_Filesystem
und wp_insert_attachment()
richtig? Oder sollte ich media_handle_upload()
stattdessen einen Weg finden, ihn zu verwenden ?
Vielen Dank!
plugin-development
ajax
uploads
media
aendrew
quelle
quelle
media_handle_upload()
Benötigen Sie eine Post-ID, und sein "Freund"wp_handle_upload()
erfordert, dass eine Datei im$_FILES
Array vorhanden ist. Ich denke also, dass sie nicht Ihren Anforderungen entsprechen. IMHO können Sie Ihren aktuellen Ansatz verwenden, wahrscheinlich hatte ichwp_upload_bits
anstelle des WP-Dateisystems verwendet. Stellen Siewpcom_vip_file_get_contents
Ihren Code außerdem nur im VIP-Wettbewerb zur Verfügung, wenn Sie einen allgemeineren Ansatzfile_get_contents
benötigen, sollte ein Standard in Ordnung sein, und wenn Sie zwischenspeichern müssen, sollte ein Transient den Trick tun.wp_upload_bits
- das ist super hilfreich. Vielen Dank!Antworten:
In einem früheren Tinymce-Plugin, das ich erstellt habe, habe ich einen benutzerdefinierten Ajax-Transport eingerichtet, sodass ich den Blob direkt aus dem Image-Quellcode eines Remote-Img anstelle von base64 für ein Datenattribut verwenden und dann das Image mithilfe der REST-API hochladen konnte die Medienbibliothek in js.
Base64 ist ungefähr 35% größer als ein Blob. Wenn also viele Diagramme oder Uploads vorhanden sind, kann dies dazu beitragen, die Upload-Bandbreite erheblich zu reduzieren. Selbst mit nur einem Bild sollte die Leistung berücksichtigt werden, da viele Benutzer dazu neigen eine Menge Plugins installiert. Sie wissen wahrscheinlich bereits, wie ressourcenintensiv nur der Editor und Tinymce sein können.
Außerdem hasse ich es, von JS zu PHP auszubrechen, wenn es nicht zu 100% notwendig ist: P.
Da Sie den Datensatz bereits in base64 haben - Sie könnten einen einfachen Konverter verwenden -, gibt es viele, die ich gerade kopiert und eingefügt habe, die ich für das folgende Beispiel gefunden habe. https://www.npmjs.com/package/base64toblob funktioniert einwandfrei, wenn Sie möchten, dass etwas schnell in Ihren Build integriert wird.
Hier ist ein schnelles Beispiel mit einem Platzhalterbild base64-Daten. Ich habe es nur zum Testen in ein Thema geworfen, aber Sie können es verwenden, wo immer Sie möchten:
theme / functions.php:
theme / js / js-plugin-name.js:
Die Datei wird wie gewohnt automatisch um -1, -2 erhöht, damit Sie keine Daten überschreiben. Yadda yadda, und die Antwort enthält das Medienobjekt mit dem, was Sie benötigen.
Einige der nützlichen Parameter als Antwort:
Wenn Sie auf base64 konvertiert haben, können Sie auch einfach einen benutzerdefinierten jquery ajax-Transport schreiben und den img src abrufen und die gesamte Base64-Dekodierung überspringen, um auch Blob-Inhalte zu erstellen.
BEARBEITEN:
Ich habe vergessen zu erwähnen: Die REST-API ist für jede VIP-Site verfügbar, daher sollte dies in Ordnung sein. Ich gehe davon aus, dass Sie die Diagramme im Tinymce-Editor im Back-End generieren - der Benutzer ist also bereits authentifiziert. Im obigen Beispiel wird die Nonce nur in einer Ajax-Anforderung über die Header übergeben. Dies ist eine Voraussetzung für die Sicherheit bei VIP.
Informationen zur Konformität finden Sie hier: https://vip.wordpress.com/documentation/api/
Ich habe auch nicht bemerkt, dass Sie HTMLCanvasElement.toDataURL () verwenden! - Sie können einfach die Dekodierung von b64 überspringen und den Blob direkt abrufen, da Sie das Bild nicht von einer Fernbedienung abrufen und versuchen, es hinzuzufügen und HTMLCanvasElement.toBlob () ( MDN ) zu verwenden.
quelle