media_handle_sideload()WP 2.6.0

Uploads a file to the WordPress media library from the provided array with file data, similar to media_handle_upload().

media_handle_upload() works directly with the global array $_FILES, which is not always convenient. Sometimes it is more convenient to specify arbitrary file data and process it, which is what this function is for.

For the function to work on the frontend, the following files are needed:

require_once ABSPATH . 'wp-admin/includes/image.php';
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/media.php';

If you need to upload an image by URL (specifically an image), use the similar function media_sideload_image().

No Hooks.

Returns

Int|WP_Error. ID of the added attachment. WP_Error object in case of failure.

Usage

$id = media_handle_sideload( $file_array, $post_id, $desc = null, $post_data = array() );
$file_array(array) (required)
Array with file data - similar to $_FILES.
$post_id(number)
ID of the post to which the file should be attached after upload.
Starting from WP 6.3, this parameter has become optional.
$desc(string)
Description of the uploaded file. Will become the value of the post_title field in wp_posts.
Default: null
$post_data(array)

Allows overwriting the data of the added attachment. Specifies the attachment data that will be written to the wp_posts table: post_parent, post_title, post_excerpt, etc. By default:

array(
	'post_mime_type' => $type,
	'guid'           => $url,
	'post_parent'    => $post_id,
	'post_title'     => $title,
	'post_content'   => $content,
)

Default: null

Examples

0

#1 Uploading a file by URL

This example shows how to work with the function. This code will download an image from an external source, add it to the WordPress media library, and attach it to the specified post:

// the frontend needs these files
//require_once ABSPATH . 'wp-admin/includes/image.php';
//require_once ABSPATH . 'wp-admin/includes/file.php';
//require_once ABSPATH . 'wp-admin/includes/media.php';

$url     = 'http://s.w.org/style/images/wp-header-logo.png';
$post_id = 3061;
$desc = "WordPress Logo";

// Load file
$tmp = download_url( $url );

/**
 * Check for download errors
 * if there are error unlink the temp file name
 */
if ( is_wp_error( $tmp ) ) {
	@unlink( $tmp );
	return $tmp;
}

//Set file data
$file_array = [
	'name'     => basename( $url ), // ex: wp-header-logo.png
	'tmp_name' => $tmp,
	'error'    => 0,
	'size'     => filesize($tmp),
];

// upload the file
$id = media_handle_sideload( $file_array, $post_id, $desc );

// if there is an error
if( is_wp_error( $id ) ) {
	@unlink($file_array['tmp_name']);
	return $id->get_error_messages();
}

// delete the temporary file
@unlink( $tmp );

// that's it, the file is loaded and should appear in the admin panel in the media files

No we can get the url of the sideloaded file $value now contains the file url in WordPress $id is the attachment id:

$value = wp_get_attachment_url( $id );

// Now you can do something with $value (or $id)
0

#2 Uploading a file by URL without linking it to any post

// the frontend needs these files
//require_once ABSPATH . 'wp-admin/includes/image.php';
//require_once ABSPATH . 'wp-admin/includes/file.php';
//require_once ABSPATH . 'wp-admin/includes/media.php';

$url = "http://s.w.org/style/images/wp-header-logo.png";
$desc = "WordPress Logo";

// load the file
$tmp = download_url( $url );

if ( ! is_wp_error( $tmp ) ) {

	// correct the filename in the query lines.
	$file_array = [
		'name'     => basename( $url ),
		'tmp_name' => $tmp
	];

	$id = media_handle_sideload( $file_array, 0 );

	// if there is an error
	if( is_wp_error( $id ) ){
		echo $id->get_error_messages();
	}

}

// delete the temporary file
@unlink( $tmp );
0

#3 Uploading an external image and setting the thumbnail of the post

A function that will download an external image from a specified URL, save it to the uploads directory and attach it to the post as a thumbnail:

// initialize function
$post_id = 3061;
$file = 'http://s.w.org/style/images/wp-header-logo.png?1';

if( is_single( $post_id ) ){
	my_sideload_image( $post_id, $file, $desc = 'Image description' );
}

// function code
function my_sideload_image( $post_id, $file, $desc = null ){

	global $debug; // defined outside the function as true

	if( ! function_exists('media_handle_sideload') ) {
		require_once ABSPATH . 'wp-admin/includes/image.php';
		require_once ABSPATH . 'wp-admin/includes/file.php';
		require_once ABSPATH . 'wp-admin/includes/media.php';
	}

	// Load the file into a temporary directory
	$tmp = download_url( $file );

	// Set variables for placement
	$file_array = [
		'name'     => basename( $file ),
		'tmp_name' => $tmp
	];

	// Delete the temporary file, in case of an error
	if ( is_wp_error( $tmp ) ) {
		$file_array['tmp_name'] = '';
		if( $debug ) echo 'Error no temporary file! <br />';
	}

	// debug checks
	if( $debug ){
		echo 'File array: <br />';
		var_dump( $file_array );
		echo '<br /> Post id: ' . $post_id . '<br />';
	}

	$id = media_handle_sideload( $file_array, $post_id, $desc );

	// Check the function
	if ( is_wp_error( $id ) ) {
		var_dump( $id->get_error_messages() );
	} else {
		update_post_meta( $post_id, '_thumbnail_id', $id );
	}

	// delete the temporary file
	@unlink( $tmp );
}

Changelog

Since 2.6.0 Introduced.
Since 5.3.0 The $post_id parameter was made optional.

media_handle_sideload() code WP 6.9

function media_handle_sideload( $file_array, $post_id = 0, $desc = null, $post_data = array() ) {
	$overrides = array( 'test_form' => false );

	if ( isset( $post_data['post_date'] ) && substr( $post_data['post_date'], 0, 4 ) > 0 ) {
		$time = $post_data['post_date'];
	} else {
		$post = get_post( $post_id );
		if ( $post && substr( $post->post_date, 0, 4 ) > 0 ) {
			$time = $post->post_date;
		} else {
			$time = current_time( 'mysql' );
		}
	}

	$file = wp_handle_sideload( $file_array, $overrides, $time );

	if ( isset( $file['error'] ) ) {
		return new WP_Error( 'upload_error', $file['error'] );
	}

	$url     = $file['url'];
	$type    = $file['type'];
	$file    = $file['file'];
	$title   = preg_replace( '/\.[^.]+$/', '', wp_basename( $file ) );
	$content = '';

	// Use image exif/iptc data for title and caption defaults if possible.
	$image_meta = wp_read_image_metadata( $file );

	if ( $image_meta ) {
		if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) {
			$title = $image_meta['title'];
		}

		if ( trim( $image_meta['caption'] ) ) {
			$content = $image_meta['caption'];
		}
	}

	if ( isset( $desc ) ) {
		$title = $desc;
	}

	// Construct the attachment array.
	$attachment = array_merge(
		array(
			'post_mime_type' => $type,
			'guid'           => $url,
			'post_parent'    => $post_id,
			'post_title'     => $title,
			'post_content'   => $content,
		),
		$post_data
	);

	// This should never be set as it would then overwrite an existing attachment.
	unset( $attachment['ID'] );

	// Save the attachment metadata.
	$attachment_id = wp_insert_attachment( $attachment, $file, $post_id, true );

	if ( ! is_wp_error( $attachment_id ) ) {
		wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file ) );
	}

	return $attachment_id;
}