0

I am trying to upload base 64 encoded images to my website media library via API. API returns with image ID but these images are displaying as blank images in my media library. Here is my code

add_action('rest_api_init', function () {
register_rest_route( 'api/v1', 'upload_image/',array(
      'methods'  => 'POST',
      'callback' => 'accept_image'
 ));
});

function accept_image($request){
$parameters = $request->get_query_params();
$parameters = $parameters['image'];

$decoded = base64_decode(str_replace('data:image/png;base64,','',$parameters));
$upload_dir = wp_upload_dir();
$upload_path = str_replace( '/', DIRECTORY_SEPARATOR, $upload_dir['path'] ) . DIRECTORY_SEPARATOR;
$filename = 'my_image.png';
$hashed_filename = md5( $filename . microtime() ) . '_' . $filename;
$image_upload = file_put_contents( $upload_path . $hashed_filename, $decoded );

//HANDLE UPLOADED FILE
if( !function_exists( 'wp_handle_sideload' ) ) {
  require_once( ABSPATH . 'wp-admin/includes/file.php' );
}

// Without that I'm getting a debug error!?
if( !function_exists( 'wp_get_current_user' ) ) {
  require_once( ABSPATH . 'wp-includes/pluggable.php' );
}

// @new
$file             = array();
$file['error']    = '';
$file['tmp_name'] = $upload_path . $hashed_filename;
$file['name']     = $hashed_filename;
$file['type']     = 'image/png';
$file['size']     = filesize( $upload_path . $hashed_filename );

// upload file to server
// @new use $file instead of $image_upload
$file_return = wp_handle_sideload( $file, array( 'test_form' => false ) );

$filename = $file_return['file'];
$attachment = array(
 'post_mime_type' => $file_return['type'],
 'post_title' => preg_replace('/\.[^.]+$/', '', basename($filename)),
 'post_content' => '',
 'post_status' => 'inherit',
 'guid' => $wp_upload_dir['url'] . '/' . basename($filename)
 );
$attach_id = wp_insert_attachment( $attachment, $filename );

return $attach_id;
}

I want to know where I have issue and how I can fix this. I will really appreciate your help.

3
  • Did my answer help? Do you need any more details? If you used a different solution, let us know about it.
    – Sally CJ
    Jun 9, 2019 at 23:59
  • 1
    Yes I have used a different solution and I have posted that in my answer. Thank you for your help @SallyCJ
    – wplearner
    Jun 14, 2019 at 15:55
  • Thanks for letting me know. :)
    – Sally CJ
    Jun 15, 2019 at 5:39

2 Answers 2

1

You should generate the attachment metadata such as width and height — and file path, and also thumbnails, after you created the attachment:

$attach_id = wp_insert_attachment( $attachment, $filename );

if ( $attach_id ) {
    require_once ABSPATH . 'wp-admin/includes/image.php';
    $metadata = wp_generate_attachment_metadata( $attach_id, $filename );
    wp_update_attachment_metadata( $attach_id, $metadata );
}
$attach_id = wp_insert_attachment( $attachment, $filename );

if ( $attachment = get_post( $attach_id ) ) {
    require_once ABSPATH . 'wp-admin/includes/image.php';
    wp_maybe_generate_attachment_metadata( $attachment );
}

Or you could simply use media_handle_sideload() instead of wp_handle_sideload() to create the attachment (and its metadata). So you'd use this in place of what you currently have in between the // upload file to server and return $attach_id;:

// upload file to server
require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/image.php';
$attach_id = media_handle_sideload( $file, 0 );

return $attach_id;
0

This function worked for me finally.

function accept_image($request){
error_reporting(E_ALL);     
//Image should be set as the body of the POST request, as a base-64 encoded string. 
//It should NOT include decorations such as data:image/png;base64, at the beginning. It should only be the encoded file itself.
//Everything else should be sent via the header

$is_valid = false;
header('Content-Type: application/json', true);
$response = array('success'=> $is_valid, 'message' => '');




$image = $request->get_body();
$decoded_file = base64_decode($image, true);
if(strlen($image) == 0 || $decoded_file === false){
    return api_msg(false, 'An error occurred during base64_decode().');
}


$content_type = $request->get_header("Content-Type");
$ext = '';
switch($content_type){
    case "image/jpg":
    case "image/jpeg":
        $ext = "jpg";
    break;
    case "image/png";
        $ext = "png";
    break;
    default:
        return api_msg(false, "Invalid Content-Type in request header. Acceptable formats are 'image/jpg' or 'image/png'.");
    break;
}





$upload_dir = wp_upload_dir();
$upload_path = str_replace( '/', DIRECTORY_SEPARATOR, $upload_dir['path'] ) . DIRECTORY_SEPARATOR;

$rand = md5( rand(3,10) .  microtime() );
$hashed_filename = "api_upload_{$rand}.{$ext}";
$image_upload = file_put_contents( $upload_path . $hashed_filename, $decoded_file );

if($image_upload === false)
return api_msg(false, "An error occurred during file_put_contents().");

$url_path = $upload_dir['url'] . '/' . $hashed_filename;
$abs_path = $upload_path . $hashed_filename;


$attachment = array(
'post_mime_type' => $content_type,
'post_title' => "API Upload - " . date('y-m-d H:i:s', time()),
'post_content' => '',
'post_status' => 'inherit',
'guid' => $url_path,
);
$attach_id = wp_insert_attachment( $attachment, $abs_path );

// 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, $abs_path );

wp_update_attachment_metadata( $attach_id, $attach_data );

return api_msg(true, "Image Saved", $attach_id, $url_path);

}

function api_msg($is_valid, $message, $id = null, $url = null){
$resp = array(
    'success' => $is_valid,
    'message' => $message
);
if(!empty($id))
    $resp['id'] = $id;
if(!empty($url))
    $resp['url'] = $url;

return $resp;
}
2
  • Don't forget to accept your answer.. =)
    – Sally CJ
    Jun 15, 2019 at 5:40
  • 1
    Yes I accepted this.
    – wplearner
    Jun 15, 2019 at 13:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.