6

My basic scenario is the following:

I have a directory on my server that gets filled with images via ftp every once in a while. I would want to move these images to the wp upload directory and then add them to the media library with wp_insert_attachment(). I thought wp_handle_sideload() to be the correct function for this but if fed with an absolute path to one of the images it returns an error.

Heres my code so far:

function oo_attach_images($images, $id){   

 //$images is an array of anbsolute image paths, $id is the id of a post I want the images to be attached to.

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

    foreach($images as $image){

        $override = array('test_form' => FALSE);

        $file = wp_handle_sideload($image, $override);

        print_r($file); //returns: Array ( [error] => )

        $attachment = array(
            'post_mime_type' => $file['type'],
            'post_title' => basename($image),
            'post_content' => ' ',
            'post_status' => 'inherit'
        );

        $attach_id = wp_insert_attachment( $attachment, $file['file'], $id );

        $attach_data = wp_generate_attachment_metadata( $attach_id, $file['file'] );
        wp_update_attachment_metadata( $attach_id,  $attach_data );


    }
}

I looked into similar questions, but none of the solutions outlined there seemed to have anything to do with the sideload itself failing. Frankly, I believe that I do not pass the right kind of file path to wp_handle_sideload(), but since its undocumented in codex I have no idea what kind of input it might expect. Does anyone know what I need to change to make this work?

1
  • I figured it out, firstly I was using the wrong function. The right one is media_handle_sideload(). The problem was, that these wp upload functions expect an array with the same structure as $_FILES passed, therefore I passed my absolute paths and other info into the function as an array similar to $_FILES. Id love to give yout the code, but thanks to the "you cant answer your own question yet" limitation ill have to wait some more before ill be able to.
    – Anatol
    Nov 25, 2011 at 16:11

4 Answers 4

1

Your files array needs to mimic the $_FILES global so you need to make a dummy page with some file inputs that prints or dumps the contents of $_FILES to see how it is structured. Make a variable that looks like that with your data and pass that wp_handle_sideload().

EDIT:

This answer was correct at the time of writing and is if you wish to use wp_handle_sideload(). media_handle_sideload() allow you to attach the media to a post at the same time.

See @anatol's own answer for a full solution.

1
7

This is the surprisingly simple code that ultimately worked out to do what it's supposed to:

function oo_attach_images($images, $id){ //$images is an array of image urls, $id is the ID of the post I want the images to be attached to

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

    foreach($images as $image){

        $array = array( //array to mimic $_FILES
            'name' => basename($image), //isolates and outputs the file name from its absolute path
            'type' => wp_check_filetype($image), // get mime type of image file
            'tmp_name' => $image, //this field passes the actual path to the image
            'error' => 0, //normally, this is used to store an error, should the upload fail. but since this isnt actually an instance of $_FILES we can default it to zero here
            'size' => filesize($image) //returns image filesize in bytes
        );

        media_handle_sideload($array, $id); //the actual image processing, that is, move to upload directory, generate thumbnails and image sizes and writing into the database happens here
    }
}
1
  • You can use wp_check_filetype to get the type. $mime_type = wp_check_filetype($image);. Available since WP 2.0.4.
    – Banjer
    Apr 24, 2015 at 18:13
5

I used Anatol's code but ran into trouble when pulling images using HTTP. To fix this, use download_url first to get a local copy of the image.

It's also useful to know that media_handle_sideload returns the attachment_id number which you can use to display the image after you've uploaded it.

foreach($images as $image){
  $tmp_name = download_url( $image ); // get the image and save it locally temporarily
  $array = array(
    'name' => basename( $image ),
    'type' => 'image/jpeg',
    'tmp_name' => $tmp_name,
    'error' => 0,
    'size' => filesize( $tmp_name )
  );
  $_image_id = media_handle_sideload($array, $id);
  $_src = wp_get_attachment_url( $_image_id );
  echo '<img src="' . $_src . '" />';
}
2

try

    { // 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 = $review['image'];
    // magic sideload image returns an HTML image, not an ID
    $media = media_sideload_image($image, $new_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' => $new_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($new_post_id, $attachment->ID);
                    // only want one image
                    break;
                }
            }
        }
    }
      } catch (Exception $e) {
          echo 'Caught exception: ',  $e->getMessage(), "\n";
      }

Your Answer

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

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