I am trying to fetch and insert images outside the wordpress environment to a custom post via PHP.

How to move/upload that image to wordpress upload directory year date folder format just like wordpress do and set that image to featured image against the custom post?

Also to upload image to custom post gallery?

Below is my code

$filename = $image['name'];
$target_path = "../wp-content/uploads/";
$target_path = $target_path . $filename;
$wp_filetype = wp_check_filetype(basename($filename), null );
$wp_upload_dir = wp_upload_dir();
$attachment = array(
    'guid' => $wp_upload_dir['baseurl'] . '/' . basename( $filename ),
    'post_mime_type' => $wp_filetype['type'],
    'post_title' => preg_replace('/\.[^.]+$/', '', basename($filename)),
    'post_content' => '',
    'post_status' => 'inherit',
$attach_id = wp_insert_attachment( $attachment, $target_path, $post_id );
$attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
wp_update_attachment_metadata( $attach_id, $attach_data );
set_post_thumbnail( $post_id, $attach_id );

i have managed to upload the image to my uploads directory but cannot unable to create the year and date folder . this there any wp function for it ??

3 Answers 3


Can't this simply be done with media_sideload_image() ?

Seems pretty simple. Only catch is if you aren't on admin area, you must include some libraries from within WordPress includes:

// only need these if performing outside of admin environment
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');

// example image
$image = 'http://example.com/logo.png';

// magic sideload image returns an HTML image, not an ID
$media = media_sideload_image($image, $post_id);

// therefore we must find it so we can set it as featured ID
if(!empty($media) && !is_wp_error($media)){
    $args = array(
        'post_type' => 'attachment',
        'posts_per_page' => -1,
        'post_status' => 'any',
        'post_parent' => $post_id

    // reference new image to set as featured
    $attachments = get_posts($args);

    if(isset($attachments) && is_array($attachments)){
        foreach($attachments as $attachment){
            // grab source of full size images (so no 300x150 nonsense in path)
            $image = wp_get_attachment_image_src($attachment->ID, 'full');
            // determine if in the $media image we created, the string of the URL exists
            if(strpos($media, $image[0]) !== false){
                // if so, we found our image. set it as thumbnail
                set_post_thumbnail($post_id, $attachment->ID);
                // only want one image
  • 1
    This solution works like a charm (y)
    – Omar Tariq
    Commented May 2, 2015 at 20:16
  • Where I can add this code ? Commented Jun 28, 2016 at 11:51
  • 2
    As of WordPress 4.8 you can set the fourth parameter in media_sideload_image to 'id' and it'll return the new attachment id. Eg: $new_att_id = media_sideload_image($image, $post_id, "image description...", 'id'); if(!is_wp_error($new_att_id)) { set_post_thumbnail($post_id, $new_att_id); }
    – Don Wilson
    Commented Mar 2, 2018 at 22:49
  • This definitely worked for me using suggestion by @DonWilson just do not forget to include the 3 media libraries if using on front end form (otherwise media_sideload_image is not found). I needed to copy featured images from one site to a separate multisite via switch_to_blog()
    – cogdog
    Commented Jun 2, 2020 at 20:58

Try this explanation of uploading using a path and post ID.

Here's the code (for legacy):

/* Import media from url
 * @param string $file_url URL of the existing file from the original site
 * @param int $post_id The post ID of the post to which the imported media is to be     attached
 * @return boolean True on success, false on failure

function fetch_media($file_url, $post_id) {
require_once(ABSPATH . 'wp-load.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');
global $wpdb;

if(!$post_id) {
    return false;

//directory to import to    
$artDir = 'wp-content/uploads/2013/06';

//if the directory doesn't exist, create it 
if(!file_exists(ABSPATH.$artDir)) {

//rename the file
$ext = array_pop(explode("/", $file_url));
$new_filename = 'blogmedia-'.$ext;

if (@fclose(@fopen($file_url, "r"))) { //make sure the file actually exists
    copy($file_url, ABSPATH.$artDir.$new_filename);

    $siteurl = get_option('siteurl');
    $file_info = getimagesize(ABSPATH.$artDir.$new_filename);

    //create an array of attachment data to insert into wp_posts table
    $artdata = array();
    $artdata = array(
        'post_author' => 1, 
        'post_date' => current_time('mysql'),
        'post_date_gmt' => current_time('mysql'),
        'post_title' => $new_filename, 
        'post_status' => 'inherit',
        'comment_status' => 'closed',
        'ping_status' => 'closed',
        'post_name' => sanitize_title_with_dashes(str_replace("_", "-", $new_filename)),                                            'post_modified' => current_time('mysql'),
        'post_modified_gmt' => current_time('mysql'),
        'post_parent' => $post_id,
        'post_type' => 'attachment',
        'guid' => $siteurl.'/'.$artDir.$new_filename,
        'post_mime_type' => $file_info['mime'],
        'post_excerpt' => '',
        'post_content' => ''

    $uploads = wp_upload_dir();
            $save_path = $uploads['basedir'].'/2013/06/'.$new_filename;

    //insert the database record
    $attach_id = wp_insert_attachment( $artdata, $save_path, $post_id );

    //generate metadata and thumbnails
    if ($attach_data = wp_generate_attachment_metadata( $attach_id, $save_path)) {
        wp_update_attachment_metadata($attach_id, $attach_data);

    //optional make it the featured image of the post it's attached to
    $rows_affected = $wpdb->insert($wpdb->prefix.'postmeta', array('post_id' => $post_id, 'meta_key' => '_thumbnail_id', 'meta_value' => $attach_id));
else {
    return false;

return true;

Perhaps I am misunderstanding, but why would you want to do that outside of the WordPress environment? Replicating this functionality would be a lot of work! WordPress does a lot more than simply uploading the file and placing it in a specific directory, for example controlling which users are allowed to upload files, adding database records for uploads and setting up featured image relationships, executing actions and filters for external plugins dependent on file upload - all while adhering to the site settings (in regards to naming conventions, media upload location, etc).

If you simply seek to upload files without being logged in to the WordPress admin section, for example for uploading files from an external site you might want to have a look at the XML-RPC API and specifically the uploadFile method.

Another option could be to write a mini API yourself. Basically what you would want to do is this:

  1. Get the file on the server through upload (or getting the server to download it from a specified URL).
  2. Use wp_upload_dir() to get the upload directory path and sanitize_file_name() to construct the path and write the file to the resulting location.
  3. Use wp_insert_attachment() to store the attachment in the database (wp_check_filetype() will be helpful for setting post_mime_type). Optionally also set post_parent and the _thumbnail_id meta key if you like.
  4. Expose your API to external users, or require login, as needed. If you use a public form at the very least use wp_create_nonce() and wp_verify_nonce() to make the form a tiny bit more secure.
  • i am writing a web service for an application. Application send me an FILE array through which i want to insert the post data and image i have inserted the post details in the database but stuck into the image part. Commented May 27, 2013 at 10:10
  • Check to documentation for wp_insert_attachment(), it should do much what you need I think. I would highly discourage manually modifying the database outside of WordPress if that's what you are doing. Instead, just look at the WordPress source and try to identify the parts responsible for adding post data, handling file uploads and inserting attachments. In other words, pretty much what I outlined in my answer above.
    – Simon
    Commented May 27, 2013 at 12:57
  • @Simon I have the same issue. Another reason you might want to upload is when you have a batch job of images you want to attach to different posts and not do it manually. Commented Jun 20, 2013 at 10:39
  • 1
    @hitautodestruct: Absolutely, I often do that when migrating data form existing sites, legacy systems, database exports etc. My point is you should always strive to take advantage of the WordPress core functionality to accomplish this, rather than just writing a script of your own that places the images at the correct location (which was to some extend what I perceived the question was about).
    – Simon
    Commented Jun 24, 2013 at 11:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.