自定义上载目录不会更改附件元

I'm trying to make a download script for a password protected wordpress site. To make use of PHPs readfile() function I need to retrieve the full attachment URL based on it's ID i am passing to the download script.

I made a Custom Post Type named Downloads and also changed it's upload directory to a folder inside wp-content also named downloads.

Here is the code for it:

add_filter( 'upload_dir', 'custom_upload_directory' );

function custom_upload_directory( $args ) {

   $id = $_REQUEST['post_id'];
   $parent = get_post( $id )->post_parent;

   if( "downloads" == get_post_type( $id ) || "downloads" == get_post_type( $parent ) ) {

      $args['path'] = WP_CONTENT_DIR . '/downloads';
      $args['url']  = WP_CONTENT_URL . '/downloads';


   }
   return $args;

}

Upload works fine and when I click the link to the desired file, the ID is passed to a script via $_POST, which also works fine. But I just can't figure out a way to get the right file URL. Here's what I tried:

wp_get_attachment_url( $id );                       // returns: example.com/wp-content/uploads/html/theme/wp-content/downloads/filename.ext
wp_get_attachment_link( $id );                      // returns: <a href="example.com/wp-content/uploads/html/theme/wp-content/downloads/filename.ext">slug</a>
get_attachment_link( $id );                         // returns: example.com/downloads/file    (without .ext)
get_attached_file( $id, true );                     // returns: html/theme/wp-content/downloads/filename.ext
get_post_meta( $id, '_wp_attached_file', false );   // returns: html/theme/wp-content/downloads/filename.ext
wp_get_attachment_metadata( $id );                  // returns nothing

What I expected any of those functions to return was example.com/wp-content/downloads/filename.ext

But as you can see, some mix up the default upload directory and combine it with the new one while others just return half of the full URL (html/theme/... it's the directory the website sits on the server). So any ideas would be appreciated.

Hours, days and even weeks later I finally found an answer and modified it to fit my needs. I came as far as displaying the right URL (the modified one) inside the file upload lightbox of Wordpress. But after publishing/updating the post it went back to the same old .../wp-content/uploads/file.ext URL.

Someone else, somewhere else got exactly the same problem and fortunately it is said there, that you must not just alter $args['path'] and $args['url'] but you also have to alter basedir, baseurl and subdir.

So, the complete code to change a custom post types upload directory (in this case I chose the directory .../wp-content/downloads) is the following:

add_filter( 'upload_dir', 'change_upload_dir' );

function change_upload_dir( $args ) {

    $id = $_REQUEST['post_id'];

    if( get_post_type( $id ) == 'downloads' ) {

      $args['basedir'] = wp_normalize_path( WP_CONTENT_DIR . 'downloads' );
      $args['baseurl'] = content_url() . '/downloads';
      $args['path']    = $args['basedir'];
      $args['url']     = $args['baseurl'];
      $args['subdir']  = '';

      return $args;

    }

}

So now, calling wp_get_attachment_url() finally results in something like example.com/wp-content/downloads/file.ext