Upload media via WordPress REST API

WordPress REST API is quite interesting especially when you are trying to update the website from some third-party resources. Recently I had to implement a similar feature where most of the things like custom post type, taxonomy etc. worked as they should except images. So, here I’m going to show how I made the media upload part work.

Although the media upload documentation says it should work with a single request, for some mysterious reason, it didn’t. I had to break the request into two parts.

Part 1: Upload the file

First I uploaded the image using a POST request. I only provided the image path in this request without any additional data.

//The image path in file system
$image_path = path/to/images/test-image.jpg;
//Upload the image
$uploaded_image = upload_image( $image_path );

I added CURL requests within the upload_image function.

function upload_image( $path ) {
    $request_url = 'http://websiteurl.com/wp/v2/media';

    $image = file_get_contents( $path );
    $mime_type = mime_content_type( $path );

    $api = curl_init();

    //set the url, POST data
    curl_setopt( $api, CURLOPT_URL, $request_url );
    curl_setopt( $api, CURLOPT_POST, 1 );
    curl_setopt( $api, CURLOPT_POSTFIELDS, $image );
    curl_setopt( $api, CURLOPT_HTTPHEADER, array( 'Content-Type: ' . $mime_type, 'Content-Disposition: attachment; filename="' . basename($path) . '"' ) );
    curl_setopt( $api, CURLOPT_RETURNTRANSFER, 1 );
    curl_setopt( $api, CURLOPT_HTTPAUTH, CURLAUTH_BASIC );
    curl_setopt( $api, CURLOPT_USERPWD, USERNAME . ':' . PASSWORD );

    //execute post
    $result = curl_exec( $api );

    //close connection
    curl_close( $api );

    return json_decode( $result );
}

The Content-Type and Content-Description values are very important while uploading image/media. Without appropriate mime type, the upload request will fail.

Part 2: Update media information

Once the image was successfully uploaded without any title, meta etc. I sent a second request to update the media.

/**
 * Let's update the image caption and other fields
 */
$fields = array(
    "date"          => date( 'Y-m-d H:i:s', $time ),
    "status"        => "publish",
    "title"         => "An interesting title for the image",
    "description"   => "Description of the image",
    "alt_text"      => "Images should have alt value",
    "caption"       => "Do not forget caption"
);
//Send the previously uploaded image ID in parameter
$updated_image = update_image_info( $uploaded_image->id, $fields );

The update_image_info function is pretty much the same as upload_image function.

function update_image_info( $id, $data = array() ) {
    $request_url = 'http://websiteurl.com/wp/v2/media/' . $id;

    $fields_string = json_encode( $data );

    $api = curl_init();

    //set the url, POST data
    curl_setopt( $api, CURLOPT_URL, $request_url );
    curl_setopt( $api, CURLOPT_POST, count($data) );
    curl_setopt( $api, CURLOPT_POSTFIELDS, $fields_string );
    curl_setopt( $api, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json' ) );
    curl_setopt( $api, CURLOPT_RETURNTRANSFER, 1 );
    curl_setopt( $api, CURLOPT_HTTPAUTH, CURLAUTH_BASIC );
    curl_setopt( $api, CURLOPT_USERPWD, USERNAME . ':' . PASSWORD );

    //execute post
    $result = curl_exec( $api );

    //close connection
    curl_close( $api );

    return json_decode( $result );
}

Notice that the Content-Type is different this time. That’s it. The $updated_image variable has the detail of newly uploaded media.

I’ve used basic authentication in the example for simplicity. But there are several other authentication methods available. Here is an interesting read about implementing OAuth2 with WP API.

 

5 thoughts on “Upload media via WordPress REST API

      1. I am pointing this out, since the exact line in your code example did not work for me, but using the line in my example did.

        For you to consider updating your example and for others to know how to make this work. (the stackoverflow way 🙂 )

  1. Thank you, Ghumkumar, for this post. It’s helped me this week.

    I needed to insert media as attachments to a post, so I wrote a small plugin that allows viewing and editing the `post_parent` attribute of post types `post` and `attachment`. It lives here: https://github.com/mistercorey/wp-api-add-post-parent

    Also, I after inserting media, I wanted to set one of them as the featured image on the parent post. That means an API request to the parent post is required to set the `featured_image` attribute to the post ID of the attachment.

    Thanks again

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.