Index: src/wp-admin/includes/media.php
===================================================================
--- src/wp-admin/includes/media.php	(revision 32828)
+++ src/wp-admin/includes/media.php	(working copy)
@@ -374,15 +374,30 @@
  *
  * @since 2.6.0
  *
- * @param array $file_array Array similar to a {@link $_FILES} upload array
+ * @param string|array $file A URL as a string, or an array similar to a {@link $_FILES} upload array
  * @param int $post_id The post ID the media is associated with
  * @param string $desc Description of the sideloaded file
  * @param array $post_data allows you to overwrite some of the attachment
  * @return int|object The ID of the attachment or a WP_Error on failure
  */
-function media_handle_sideload($file_array, $post_id, $desc = null, $post_data = array()) {
-	$overrides = array('test_form'=>false);
+function media_handle_sideload( $file, $post_id, $desc = null, $post_data = array()) {
 
+	if ( is_string( $file ) ) {
+
+		$file = array(
+			'name'     => basename( preg_replace( '/\?.*/', '', $file ) ), // fix file filename for query strings
+			'tmp_name' => download_url( $file ),
+		);
+
+		// If error storing temporarily, return the error.
+		if ( is_wp_error( $file['tmp_name'] ) ) {
+			return $file['tmp_name'];
+		}
+
+	}
+
+	$overrides = array( 'test_form' => false );
+
 	$time = current_time( 'mysql' );
 	if ( $post = get_post( $post_id ) ) {
 		if ( substr( $post->post_date, 0, 4 ) > 0 )
@@ -389,9 +404,12 @@
 			$time = $post->post_date;
 	}
 
-	$file = wp_handle_sideload( $file_array, $overrides, $time );
-	if ( isset($file['error']) )
+	$file = wp_handle_sideload( $file, $overrides, $time );
+
+	if ( isset($file['error']) ) {
+		@unlink( $file['tmp_name'] );
 		return new WP_Error( 'upload_error', $file['error'] );
+	}
 
 	$url = $file['url'];
 	$type = $file['type'];
@@ -424,8 +442,9 @@
 
 	// Save the attachment metadata
 	$id = wp_insert_attachment($attachment, $file, $post_id);
-	if ( !is_wp_error($id) )
+	if ( ! is_wp_error( $id ) ) {
 		wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $file ) );
+	}
 
 	return $id;
 }
Index: tests/phpunit/tests/media.php
===================================================================
--- tests/phpunit/tests/media.php	(revision 32828)
+++ tests/phpunit/tests/media.php	(working copy)
@@ -572,4 +572,39 @@
 		$this->assertEquals( 'This is a comment. / Это комментарий. / Βλέπετε ένα σχόλιο.', $post->post_excerpt );
 	}
 
+	/**
+	 * @ticket 19629
+	 */
+	function test_sideload_media() {
+
+		$post_id = wp_insert_post( array(
+			'post_title'  => 'test sideload media post',
+			'post_status' => 'publish'
+		) );
+
+		// Test sideloading image.
+		// Note source image has to be 'external'
+		$url = 'https://s.w.org/about/images/logos/wordpress-logo-notext-rgb.png';
+		$id = media_handle_sideload( $url, $post_id );
+		$this->assertTrue( is_int( $id ) );
+		wp_delete_attachment( $id, true );
+
+		// Test sideloading image by passing file array.
+		// Note source image has to be 'external'
+		$url = 'https://s.w.org/about/images/logos/wordpress-logo-notext-rgb.png';
+		$id = media_handle_sideload( array( 'name' => 'test.png', 'tmp_name' => download_url( $url ) ), $post_id );
+		$this->assertTrue( is_int( $id ) );
+		wp_delete_attachment( $id, true );
+
+		// Test sideloading 404.
+		// Note source should return 404.
+		$url = 'https://wordpress.org/image-not-found.png';
+		$id = media_handle_sideload( $url, $post_id );
+		$this->assertTrue( is_wp_error( $id ) );
+
+		// Cleanup.
+		wp_delete_post( $post_id, true );
+
+	}
+
 }
