How Can I Organize the Uploads Folder by Slug (or ID, or FileType, or Author)?

I want to store all attachments (media) in folders named with each post title.

Example: /wp-content/uploads/my-post-about-stuff/

The folder should contain all media attached to that post.

Is that possible?

3 s
3

Disclaimer

  • Tracking the way to do the same using the post_id
  • Having already answered one question about separating PDF’s from the rest
  • Found disperse questions about this matter
  • Decided to adopt this Q as the venue to publish this.

Follow the instructions in the comments, and this code can be adapted to organize the uploads folder by post_name (aka: slug), post_author, post_id or media type.

add_filter('wp_handle_upload_prefilter', 'wpse_25894_handle_upload_prefilter');
add_filter('wp_handle_upload', 'wpse_25894_handle_upload');

function wpse_25894_handle_upload_prefilter( $file )
{
    add_filter('upload_dir', 'wpse_25894_custom_upload_dir');
    return $file;
}

function wpse_25894_handle_upload( $fileinfo )
{
    remove_filter('upload_dir', 'wpse_25894_custom_upload_dir');
    return $fileinfo;
}

function wpse_25894_custom_upload_dir($path)
{   
    /*
     * Determines if uploading from inside a post/page/cpt - if not, default Upload folder is used
     */
    $use_default_dir = ( isset($_REQUEST['post_id'] ) && $_REQUEST['post_id'] == 0 ) ? true : false; 
    if( !empty( $path['error'] ) || $use_default_dir )
        return $path; //error or uploading not from a post/page/cpt 
    
    /*
     * Save uploads in ID based folders 
     *
     */
    
    /*
     $customdir="https://wordpress.stackexchange.com/" . $_REQUEST['post_id'];
    */


    /*
     * Save uploads in SLUG based folders 
     *
     */
    
     $the_post = get_post($_REQUEST['post_id']);
     $customdir="https://wordpress.stackexchange.com/" . $the_post->post_name;


    /*
     * Save uploads in AUTHOR based folders 
     *
     * ATTENTION, CAUTION REQUIRED: 
     * This one may have security implications as you will be exposing the user names in the media paths
     * Here, the *display_name* is being used, but normally it is the same as *user_login*
     *
     * The right thing to do would be making the first/last name mandatories
     * And use:
     * $customdir="https://wordpress.stackexchange.com/" . $the_author->first_name . $the_author->last_name;
     *
     */
    
    /* 
      $the_post = get_post($_REQUEST['post_id']);
      $the_author = get_user_by('id', $the_post->post_author);
      $customdir="https://wordpress.stackexchange.com/" . $the_author->data->display_name;
    */
    
    
    /*
     * Save uploads in FILETYPE based folders 
     * when using this method, you may want to change the check for $use_default_dir
     *
     */
    
    /*
     $extension = substr( strrchr( $_POST['name'], '.' ), 1 );
     switch( $extension )
     {
        case 'jpg':
        case 'png':
        case 'gif':
            $customdir="/images";
            break;
            
        case 'mp4':
        case 'm4v':
            $customdir="/videos";
            break;
        
        case 'txt':
        case 'doc':
        case 'pdf':
            $customdir="/documents";
            break;
     
        default:
            $customdir="/others";
            break;
     }
    */
    
    $path['path']    = str_replace($path['subdir'], '', $path['path']); //remove default subdir (year/month)
    $path['url']     = str_replace($path['subdir'], '', $path['url']);      
    $path['subdir']  = $customdir;
    $path['path']   .= $customdir; 
    $path['url']    .= $customdir;  

    return $path;
}

Leave a Comment