Last active
June 23, 2025 17:51
-
-
Save RadGH/966f8c756c5e142a5f489e86e751eacb to your computer and use it in GitHub Desktop.
Upload a file from a URL to the WordPress media gallery. Supports images, PDFs, and other file types.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* This function uploads a file from a URL to the media library, designed to be placed in your own theme or plugin. | |
* Metadata will be generated and images will generate thumbnails automatically. | |
* | |
* HOW TO USE: | |
* 1. Add the function below to your theme or plugin | |
* 2. Call the function and provide the URL to an image or other file. | |
* 3. If successful, the attachment ID will be returned. | |
* | |
* BASIC USAGE: | |
* $attachment_id = rs_upload_from_url( "https://www.gstatic.com/webp/gallery/1.jpg" ); | |
* if ( $attachment_id ) echo wp_get_attachment_image( $attachment_id, 'large' ); | |
* | |
* DOWNLOAD AS A PLUGIN (optional): | |
* Below is a link to a separate plugin you can upload to your site to help get started. | |
* It is a fully-functional example and demonstrates upload both JPG and WEBP image by using a "secret" url. | |
* It also provides an easy way to delete the test images that were created. | |
* @see https://gist.github.com/RadGH/be30af96617b13e7848a4626ef179bbd | |
* | |
* To upload from a *LOCAL FILE PATH* instead of a URL: | |
* @see: https://gist.github.com/RadGH/3b544c827193927d1772 | |
*/ | |
/** | |
* Upload a file to the media library using a URL. | |
* | |
* @version 1.4 | |
* @author Radley Sustaire | |
* @see https://gist.github.com/RadGH/966f8c756c5e142a5f489e86e751eacb | |
* | |
* @param string $url URL to be uploaded | |
* @param null|string $title Override the default post_title | |
* @param null|string $content Override the default post_content (Added in 1.3) | |
* @param null|string $alt Override the default alt text (Added in 1.3) | |
* @param null|string $caption Override the default caption / post excerpt (Added in 1.4) | |
* | |
* @return int|false | |
*/ | |
function rs_upload_from_url( $url, $title = null, $content = null, $alt = null, $caption = null ) { | |
require_once( ABSPATH . "/wp-load.php"); | |
require_once( ABSPATH . "/wp-admin/includes/image.php"); | |
require_once( ABSPATH . "/wp-admin/includes/file.php"); | |
require_once( ABSPATH . "/wp-admin/includes/media.php"); | |
// Download url to a temp file | |
$tmp = download_url( $url ); | |
if ( is_wp_error( $tmp ) ) return false; | |
// Ignore query params to fix issues with certain URLS | |
// @see https://gist.github.com/RadGH/966f8c756c5e142a5f489e86e751eacb?permalink_comment_id=5626880#gistcomment-5626880 | |
$url_path = parse_url($url, PHP_URL_PATH); | |
// Get the filename and extension ("photo.png" => "photo", "png") | |
$filename = pathinfo($url_path, PATHINFO_FILENAME); | |
$extension = pathinfo($url_path, PATHINFO_EXTENSION); | |
// An extension is required or else WordPress will reject the upload | |
if ( ! $extension ) { | |
// Look up mime type, example: "/photo.png" -> "image/png" | |
$mime = mime_content_type( $tmp ); | |
$mime = is_string($mime) ? sanitize_mime_type( $mime ) : false; | |
// Only allow certain mime types because mime types do not always end in a valid extension (see the .doc example below) | |
$mime_extensions = array( | |
// mime_type => extension (no period) | |
'text/plain' => 'txt', | |
'text/csv' => 'csv', | |
'application/msword' => 'doc', | |
'image/jpg' => 'jpg', | |
'image/jpeg' => 'jpeg', | |
'image/gif' => 'gif', | |
'image/png' => 'png', | |
'video/mp4' => 'mp4', | |
); | |
if ( isset( $mime_extensions[$mime] ) ) { | |
// Use the mapped extension | |
$extension = $mime_extensions[$mime]; | |
}else{ | |
// Could not identify extension. Clear temp file and abort. | |
wp_delete_file($tmp); | |
return false; | |
} | |
} | |
// Upload by "sideloading": "the same way as an uploaded file is handled by media_handle_upload" | |
$args = array( | |
'name' => "$filename.$extension", | |
'tmp_name' => $tmp, | |
); | |
// Post data to override the post title, content, and alt text | |
$post_data = array(); | |
if ( $title ) $post_data['post_title'] = $title; | |
if ( $content ) $post_data['post_content'] = $content; | |
if ( $caption ) $post_data['post_excerpt'] = $caption; | |
// Do the upload | |
$attachment_id = media_handle_sideload( $args, 0, null, $post_data ); | |
// Clear temp file | |
wp_delete_file($tmp); | |
// Error uploading | |
if ( is_wp_error($attachment_id) ) return false; | |
// Save alt text as post meta if provided | |
if ( $alt ) update_post_meta( $attachment_id, '_wp_attachment_image_alt', $alt ); | |
// Success, return attachment ID | |
return (int) $attachment_id; | |
} |
@acot123 There is very basic support for that, but you will probably have to customize this part further: if ( ! $extension ) { ... }
You'll need to verify the mime_content_type is loading correctly and adjust the array of extensions if necessary.
Thanks a lot for this code! :) Two tweaks I needed in case you need them too:
Ignore query params so that URLs like this won't create a broken file.
// Get the filename and extension (".../folder/photo.png?query=..." => "photo", "png")
$url_path = parse_url($url, PHP_URL_PATH);
$filename = pathinfo($url_path, PATHINFO_FILENAME);
$extension = pathinfo($url_path, PATHINFO_EXTENSION);
Set image caption if you need it.
function bc_upload_from_url([...], $caption = null ) {
[...]
if ( $caption ) $post_data['post_excerpt'] = $caption;
@brickup-de Thanks for the contribution! I've added those to the original function, I think they are both useful additions.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
The script works perfectly for URLs that have extensions like .jpg.
Can the code be adjusted for images from a URL that doesn’t have an extension, but the image can still be downloaded in jpg format?
An example is a Hikvision camera with the URL: http://user:password@publicIP/ISAPI/Streaming/channels/101/picture.
As you can see, the URL doesn’t have an extension at the end, but when the link is opened, the image is displayed and can be downloaded as a jpg.
another example is: https://unsplash.com/photos/woman-with-dslr-camera-e616t35Vbeg