Skip to content

Instantly share code, notes, and snippets.

@ahmadawais
Forked from websupporter/upload-a-file.MD
Created June 18, 2017 11:07
Show Gist options
  • Save ahmadawais/0ccb8a32ea795ffac4adfae84797c19a to your computer and use it in GitHub Desktop.
Save ahmadawais/0ccb8a32ea795ffac4adfae84797c19a to your computer and use it in GitHub Desktop.
Upload a file using the WordPress REST API

Upload files

Using the REST API to upload a file to WordPress is quite simple. All you need is to send the file in a POST-Request to the wp/v2/media route.

There are two ways of sending a file. The first method simply sends the file in the body of the request. The following PHP script shows the basic principle:

<?php

$file = file_get_contents( 'test.jpg' );
$url = 'http://example.com/wp-json/wp/v2/media/';
$ch = curl_init();
$username = 'admin';
$password = 'password';

curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POST, 1 );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $file );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
	'Content-Disposition: form-data; filename="example.jpg"',
	'Authorization: Basic ' . base64_encode( $username . ':' . $password ),
] );
$result = curl_exec( $ch );
curl_close( $ch );
print_r( json_decode( $result ) );

This would send the file test.jpg using CURL and create a new attachment.

You need to make sure, you are logged in as a user, who can upload media files. In our example, we are using Basic authentication. Via the headers you also have to send the Content-Disposition where you also add the filename.

The file itself is simply send in the body of the request.

The disadvantage of this way is, you can upload the file, but you can not alter the title or the caption in the same process. You would need to wait for the response and you would need to update the created media object in a second request.

Upload a file using Javascript

Have a look into this small plugin, to see one possibility, how to upload a file using Javascript:

plugin.php

<?php
/**
 * Plugin Name: Upload a file via the REST API
 * Description: Upload a file with Javascript using the Rest API.
 * License: GPLv2
 */

add_action( 'wp_enqueue_scripts', function() {

	wp_register_script( 'rest-uploader', plugins_url( '/assets/js/script.js', __FILE__ ), [ 'jquery' ] );
	$js_vars = [
		'endpoint' => esc_url_raw( rest_url( '/wp/v2/media/' ) ),
		'nonce'    => wp_create_nonce( 'wp_rest' ),
	];
	wp_localize_script( 'rest-uploader', 'RestVars', $js_vars );
} );

add_shortcode( 'uploader', function() {
	wp_enqueue_script( 'rest-uploader' );
	ob_start();
	?>

	<h2><?php esc_html_e( 'Upload a file', 'rest-uploader' ); ?></h2>
	<form method="post">
		<p>
			<label for="uploader-title">
				<?php esc_html_e( 'Title', 'rest-uploader' ); ?>:
			</label>
			<input id="uploader-title">

		</p>
		<p>
			<label for="uploader-caption">
				<?php esc_html_e( 'Caption', 'rest-uploader' ); ?>:
			</label>
			<input id="uploader-caption">

		</p>
		<p>
			<label for="uploader-file">
				<?php esc_html_e( 'File', 'rest-uploader' ); ?>:
			</label>
			<input id="uploader-file" type="file">
		</p>
		<button id="uploader-send"><?php esc_html_e( 'Send', 'rest-uploader' ); ?></button>
	</form>
	<?php
	$content = ob_get_contents();
	ob_end_clean();
	return $content;
} );

In this plugin, we simply add a shortcode, which renders a basic form and hooks the following Javascript in:

assets/js/script.js

jQuery( document ).ready( function() {
	jQuery( '#uploader-send' ).click( function( event ) {

		event.preventDefault();

		var title = jQuery( '#uploader-title' ).val();
		if ( ! title.length ) {
			alert( 'Please enter a title!' );
		}
		var caption = jQuery( '#uploader-caption' ).val();
		if ( ! caption.length ) {
			alert( 'Please enter a caption!' );
		}
		// Check, if a file is selected.
		if ( 'undefined' === typeof( jQuery( '#uploader-file' )[0].files[0] ) ) {
			alert( 'Select a file!' );
			return;
		}
		// Grab the file from the input.
		var file = jQuery( '#uploader-file' )[0].files[0];
		var formData = new FormData();
		formData.append( 'file', file );
		formData.append( 'title', title );
		formData.append( 'caption', caption );

		// Fire the request.
		jQuery.ajax( {
			url: RestVars.endpoint,
			method: 'POST',
			processData: false,
			contentType: false,
			beforeSend: function ( xhr ) {
				xhr.setRequestHeader( 'X-WP-Nonce', RestVars.nonce );
			},
			data: formData
		} ).success( function ( response ) {
			console.log( response.id )
		} ).error( function( response ) {
			console.log( 'error' );
			console.log( response );
		});
	} );
});

Basically, we are using Javascripts FormData-class to generate our form data and send this data to our rest endpoint. As we are not using the while requests body to send the file, in this example, we can upload a file and create the attachment in one request.

@mizner
Copy link

mizner commented Oct 25, 2017

FormData is the key here, thanks for this @ahmadawais. Super helpful!

@jongood01
Copy link

This doesn't work - the attachment get's created but the file is not stored in the uploads. Seems that endpoint is only for creating the attachment see on of the answers on: https://wordpress.stackexchange.com/questions/209928/add-media-with-wp-rest-api-v2

@tunglatui94
Copy link

Thank you @ahmadawais! The part script.js is so great!

@ZalgirisKaunas
Copy link

this works great, but how could I use formData for multiple files?

@smakman
Copy link

smakman commented Aug 28, 2019

I had to add the following line to be able to assign the response to $result:

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

@rodvan
Copy link

rodvan commented Dec 17, 2019

{"code":"jwt_auth_bad_auth_header","message":"Authorization header malformed.","data":{"status":403}}

@atashinbar
Copy link

atashinbar commented Jun 16, 2020

{"code":"jwt_auth_bad_auth_header","message":"Authorization header malformed.","data":{"status":403}}

Did you send token as a header parameter for authentication?

@emirhangumus
Copy link

THANK YOU SO MUCH <3 <3 <3 <3

@F3rrY
Copy link

F3rrY commented Feb 2, 2022

I'm trying to make a image upload using restsharp and I can't... Where is the equivalent of CURLOPT_POSTFIELDS in C#? I have to send the bytes of the image?

@hony10
Copy link

hony10 commented Jan 4, 2023

@ahmadawais Brother I am using this php code, curl request send successfully but not able to display image on editor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment