Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 764 Vote(s) - 3.41 Average
  • 1
  • 2
  • 3
  • 4
  • 5
WP_REST_Response to download a file

#1
Is it possibile to return a document (a generated PDF, a CSV) using the `WP_REST_Response` in WordPress?

So far I've been registering a custom endpoint using `register_rest_resource` but if I try to return a file (e.g. using PHP `fpassthru($f)` or `readfile($f)` I get the "Headers already sent" error.

Using other words: how you would return a file using Wordpress REST APIs?

Any help is appreciated!

Thanks
Reply

#2
(I need this myself soon so formulating an answer which maybe incomplete)

Checking with WP Media we get on `.../?rest_route=/wp/v2/media/ID` a `JSON API` response having links for the media file(s) asked for.

Following along ie for image one of the `source _url` contains `.../wp-content/uploads/2021/06/Screenshot-2021-06-18-at-10.25.05-150x150.png`.

Following the comments (do not stream binary but link) add the file to WP Media collection or the custom endpoint could respond with a similar response linking to the generated AND stored file.

Then any JSON API compatible client can do what is needed. In this case generate a download link.
Reply

#3
You cannot use `WP_REST_Response` to do this. It is however possible to return something else with the rest api.

If you're absolutely sure you have the *complete* response ready (including headers, like `Content-Disposition` for downloads), you can simply `exit;` after generating the final response. Do note that this completely bypasses any hooks that would've been called afterwards, so use with caution.

An example with `.csv`
-

```php
$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;
Reply

#4
By default, all REST responses are passed through `json_encode()` to return a JSON string. However, the REST server provides the WP hook [**`rest_pre_serve_request`**][1] that we can use to return binary data instead.

**Code sample:**

```php
<?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;
}
```

**Sample usage:**

```php
<?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' );
}
```


[1]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
2 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through