Change upload directory on custom plugin page

The question:

I am trying to change the path to my uploads directory when on this one specific page in my custom plugin. The page is a standard php page and not any specific type of post type page.

I have found numerous articles explaining the process, and I can see how it would work if this were a custom post type, but seeing as it’s not the examples are not working as intended.

The URL to my custom page is as follows:

the $_POST variable is dynamic based on the item that the user is editing.

I have come across the following and adjusted it to my needs:

function edd_load_upload_filter() {
    global $pagenow;

    if ( ! empty( $_POST['page'] ) && $_POST['page'] == 'custom-plugin-page' && ( 'async-upload.php' == $pagenow || 'media-upload.php' == $pagenow ) ) {
        add_filter( 'upload_dir', 'edd_set_upload_dir' );
add_action('admin_init', 'edd_load_upload_filter');

function edd_set_upload_dir($upload) {
    $upload['subdir']   = '/edd' . $upload['subdir'];
    $upload['path'] = $upload['basedir'] . $upload['subdir'];
    $upload['url'] = $upload['baseurl'] . $upload['subdir'];
    return $upload;

But as you can see, the function is checking if the post type is type ‘download’.

From what I can tell, the $_POST variable is not empty on initial page load, but when the media modal is opened it is empty. Since it returns as empty inside the media modal, the path to the upload directory does not properly get set. If I remove the !empty( $_POST[
page'] );
check the path is properly adjusted, but then it gets adjusted across the entire site and not just on my custom page.

Not sure why the examples on the net all use some $_POST or $_REQUEST variable, but when I go to use it, it is empty so my function never fires. Any ideas?

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

After working on this for a bit and checking the GLOBALS variable for anything useful, it looks like the referring URL inside of the media modal is the same URL as my custom plugin page.

Using that and splitting it up a bit I was able to confirm that I am on the approrpriate page. I’m sure that there are other, more elegant solutions out there, but this is what I was able to come up with. I have tested and it seems to be working properly.

Here is my final solution :

    add_filter( 'admin_init' , 'check_if_we_should_change_upload_dir', 999 );
    function check_if_we_should_change_upload_dir() {   
            global $pagenow;
            $referrer = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : '';
            if( $referrer != '' ) {
                $explode_1 = explode( 'page=' , $referrer );
                if( isset( $explode_1[1] ) ) {
                    $referring_page = explode( '&id=' , $explode_1[1] );
                    if( isset( $referring_page[0] ) && $referring_page[0] == 'custom-plugin-page' && ( 'async-upload.php' == $pagenow || 'media-upload.php' == $pagenow ) ) {
                        add_filter( 'upload_dir', 'alter_the_upload_dir' );

  function alter_the_upload_dir( $upload ) {
        $upload['subdir'] = '/custom-directory' . $upload['subdir'];
        $upload['path'] = $upload['basedir'] . $upload['subdir'];
        $upload['url']  = $upload['baseurl'] . $upload['subdir'];
        return $upload;

If anyone has any better solutions to checking, I am all ears!


Method 2

Thanks EHerman for your solution. My simplified version of your script would use the HTTP_REFERER in the upload filter directly:

function my_custom_upload_dir($path) {

  if(isset( $_SERVER['HTTP_REFERER'] )) {
    //parse url into array
    $referrer = parse_url($_SERVER['HTTP_REFERER']);
    // take the query part and parse it into array
    parse_str($referrer['query'], $queries);

   // check for anything that was in the query string of the current screen
   // you can use what ever you see in the wp-admin url before the upload frame opens    
    if( isset($queries['taxonomy']) ) {

        $mydir = '/taxonomy-files';

        $path['subdir']  = $mydir;
        $path['path']   = $path['basedir'].$mydir; 
        $path['url']    = $path['baseurl'].$mydir;  

  return $path; //altered or not

And to use the filter correctly

add_filter('wp_handle_upload_prefilter', 'my_upload_prefilter');
add_filter('wp_handle_upload', 'my_handle_upload');

function my_upload_prefilter( $file ) {
    add_filter('upload_dir', 'my_custom_upload_dir');
    return $file;

function my_handle_upload( $fileinfo ) {
    remove_filter('upload_dir', 'my_custom_upload_dir');
    return $fileinfo;

All methods was sourced from or, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment