Front-end File Uploads in WordPress

| Comments

I was recently working on a WordPress project that required a specialized front-end panel for users to add new posts, including images and videos. Adding a post wasn’t a challenge, but handling file uploads was looking like a pain… at least trying to follow the codex documentation. After browsing the wp-includes core files for a few hours, though, I found a much easier way of handling it.

According to the

codex entry for wp_insert_attachment, adding an attachment to a post should be achieved by a function like the following:

$wp_filetype = wp_check_filetype(basename($filename), null );
  $attachment = array(
     'post_mime_type' => $wp_filetype['type'],
     'post_title' => preg_replace('/\.[^.]+$/', '', basename($filename)),
     'post_content' => '',
     'post_status' => 'inherit'
  );
  $attach_id = wp_insert_attachment( $attachment, $filename, 37 );
  // you must first include the image.php file
  // for the function wp_generate_attachment_metadata() to work
  require_once(ABSPATH . "wp-admin" . '/includes/image.php');
  $attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
  wp_update_attachment_metadata( $attach_id,  $attach_data );

I spent several hours struggling to make this function work. The wp_insert_attachment() function is simple enough—it will take an uploaded file, given a server path, and add it as an entry to the wp_posts table with type “attachment”. So if you’ve already processed the user upload, sanitized the title, checked the mime-type, and saved it to your uploads directory, this step is simple enough. The functions in lines 12 and 13, wp_generate_attachment_metadata() and wp_update_attachment_metadata(), set the attachment’s mime-type and associate it with the proper post parent.

But there’s something glaring missing here. In order to use an uploaded image with any of WordPress’s built-in image functions, you really need to generate thumbails and all the intermediate and custom image sizes that work with get_the_post_thumbnail, get_attachment_image, and all the other attachment-related image functions. And for most sites, trusting users to upload images at a specific size isn’t really an option. I’m not about to have my entire layout broken because someone uploaded a 6 megapixel jpg as the thumbnail for their post.

So how does WordPress go about creating these intermediate sizes? I looked around the wp-admin files to see how its done within the admin panel. I came across a couple really handy functions in wp-admin/includes/media.php. The one which worked for me was media_handle_upload(). This function does everything from sanitizing and ensuring unique name for the file, resizing the uploaded file to all the intermediate sizes, and generating and updating the attachment metadata.

So, long story short, my function for handling user-uploaded images was reduced from a 40-line monstrosity to this simple, easy, and secure function:

function insert_attachment($file_handler,$post_id,$setthumb='false') {

  // check to make sure its a successful upload
  if ($_FILES[$file_handler]['error'] !== UPLOAD_ERR_OK) __return_false();

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

  $attach_id = media_handle_upload( $file_handler, $post_id );

  if ($setthumb) update_post_meta($post_id,'_thumbnail_id',$attach_id);
  return $attach_id;
}

Very satisfying. While I was looking for this code, I saw a lot of questions in support forums from other people trying to get similar functionality. So I’m posting this in case it helps anyone. Happy coding!