Ist es möglich, ein Dokument (ein generiertes PDF, eine CSV) mit dem zurückzugeben WP_REST_Response
bei WordPress?
Bisher habe ich einen benutzerdefinierten Endpunkt mit registriert register_rest_resource
aber wenn ich versuche, eine Datei zurückzugeben (z. B. mit PHP fpassthru($f)
oder readfile($f)
Ich erhalte die Fehlermeldung „Header bereits gesendet“.
Mit anderen Worten: Wie würden Sie eine Datei mit WordPress REST APIs zurückgeben?
Jede Hilfe ist willkommen!
Vielen Dank
Standardmäßig werden alle REST-Antworten durchgeleitet json_encode()
um einen JSON-String zurückzugeben. Der REST-Server stellt jedoch den WP-Hook bereit rest_pre_serve_request
die wir verwenden können, um stattdessen binäre Daten zurückzugeben.
Codebeispiel:
<?php
/**
* Serves an image via the REST endpoint.
*
* By default, every REST response is passed through json_encode(), as the
* typical REST response contains JSON data.
*
* This method hooks into the REST server to return a binary image.
*
* @param string $path Absolute path to the image to serve.
* @param string $type The image mime type [png|jpg|gif]. Default is 'png'.
*
* @return WP_REST_Response The REST response object to serve an image.
*/
function my_serve_image( $path, $type="png" ) {
$response = new WP_REST_Response;
if ( file_exists( $path ) ) {
// Image exists, prepare a binary-data response.
$response->set_data( file_get_contents( $path ) );
$response->set_headers( [
'Content-Type' => "image/$type",
'Content-Length' => filesize( $path ),
] );
// HERE → This filter will return our binary image!
add_filter( 'rest_pre_serve_request', 'my_do_serve_image', 0, 2 );
} else {
// Return a simple "not-found" JSON response.
$response->set_data( 'not-found' );
$response->set_status( 404 );
}
return $response;
}
/**
* Action handler that is used by `serve_image()` to serve a binary image
* instead of a JSON string.
*
* @return bool Returns true, if the image was served; this will skip the
* default REST response logic.
*/
function my_do_serve_image( $served, $result ) {
$is_image = false;
$image_data = null;
// Check the "Content-Type" header to confirm that we really want to return
// binary image data.
foreach ( $result->get_headers() as $header => $value ) {
if ( 'content-type' === strtolower( $header ) ) {
$is_image = 0 === strpos( $value, 'image/' );
$image_data = $result->get_data();
break;
}
}
// Output the binary data and tell the REST server to not send any other
// details (via "return true").
if ( $is_image && is_string( $image_data ) ) {
echo $image_data;
return true;
}
return $served;
}
Beispielverwendung:
<?php
// Register the REST endpoint.
register_rest_route( 'my_sample/v1', 'image', [
'method' => 'GET',
'callback' => 'my_rest_get_image'
] );
// Return the image data using our function above.
function my_rest_get_image() {
return my_serve_image( 'path/to/image.jpeg', 'jpg' );
}
(Ich brauche das bald selbst, um eine Antwort zu formulieren, die vielleicht unvollständig ist.)
Nach Rücksprache mit WP Media kommen wir weiter .../?rest_route=/wp/v2/media/ID
a JSON API
Antwort mit Links für die angeforderten Mediendateien.
Entlang dh für Bild eines der folgen source _url
enthält .../wp-content/uploads/2021/06/Screenshot-2021-06-18-at-10.25.05-150x150.png
.
Folgen Sie den Kommentaren (nicht binär streamen, sondern verknüpfen), fügen Sie die Datei zur WP Media-Sammlung hinzu, oder der benutzerdefinierte Endpunkt könnte mit einer ähnlichen Antwort antworten, die mit der generierten UND gespeicherten Datei verknüpft ist.
Dann kann jeder JSON-API-kompatible Client das tun, was erforderlich ist. Generieren Sie in diesem Fall einen Download-Link.
Sie können nicht verwenden WP_REST_Response
um dies zu tun. Es ist jedoch möglich, etwas anderes mit der Rest-API zurückzugeben.
Wenn Sie absolut sicher sind, dass Sie die haben Komplett antwortbereit (einschließlich Header, wie z Content-Disposition
für Downloads), können Sie einfach exit;
nach dem Generieren der endgültigen Antwort. Beachten Sie, dass dies alle Hooks, die danach aufgerufen worden wären, vollständig umgeht, also verwenden Sie es mit Vorsicht.
Ein Beispiel mit .csv
$filename="example-file.csv";
header("Access-Control-Expose-Headers: Content-Disposition", false);
header('Content-type: text/csv');
header("Content-Disposition: attachment; filename=\"$filename\"");
// output starts here, do not add headers from this point on.
$csv_file = fopen('php://output', 'w');
$csv_header = array(
'column-1',
'column-2',
'column-3',
);
fputcsv($csv_file, $csv_header);
$data = array(
array('a1', 'b1', 'c1'),
array('a2', 'b2', 'c2'),
array('a3', 'b3', 'c3'),
);
foreach ($data as $csv_data_entry) {
fputcsv($csv_file, $csv_data_entry);
}
fclose($csv_file);
// With a non-file request, you would usually return the result.
// In this case, this would cause the "Headers already sent" errors, so an exit is required.
exit;
13931800cookie-checkWP_REST_Response zum Herunterladen einer Dateiyes
“Zurückkommen zu dem? Die API gibt JSON zurück. Wenn Ihre Frage also grundsätzlich lautet: „Kann ich binäre Daten in JSON einfügen“, dann wäre die Antwort ja. Ob man das tun sollte oder unter welchen Umständen es sinnvoll sein könnte, wäre eine andere Frage.
– CBroe
13. Juni 2017 um 14:20 Uhr
Ich stimme zu, dass die API JSON an den JS-Aufgerufenen zurückgeben sollte. Aber was ist, wenn meine API (zum Beispiel) eine ID einer Bestellung als Eingabe nimmt und das PDF der Rechnung dieser Bestellung zurückgeben soll?
– Diego Viganò
13. Juni 2017 um 14:40 Uhr
Dann würde ich dies als Designfehler betrachten :p Große binäre Assets sollten überhaupt nicht über eine solche API herumgereicht werden. Ihre API sollte a zurückgeben URL für das PDF, das der Kunde dann zum Download verwenden kann.
– CBroe
13. Juni 2017 um 14:42 Uhr
Ja, aber dies würde zwei Aufrufe erfordern: den ersten, um die PDF-Datei zu generieren und auf der Serverfestplatte zu speichern, und einen zweiten, um die auf der Festplatte gespeicherte PDF-Datei tatsächlich herunterzuladen.
– Diego Viganò
13. Juni 2017 um 16:18 Uhr
URLs müssen nicht auf „statische“ Daten oder Dateien verweisen.
– CBroe
13. Juni 2017 um 16:49 Uhr