Extra “uploads” added in path

Although this is related to Advanced Custom Fields, this function uses all native WP features, so I think this is appropriate to ask here. Where is the extra "/uploads/" in path is coming from here?

In the back-end, I see correct links to uploaded files (domain.com/wp-content/member-files/name.pdf), but on the front-end, the URLs display with an extra "/uploads/" in path (domain.com/wp-content/uploads/member-files/name.pdf), and of course produces a 404 for the file.

// file upload to custom location

add_filter( 'acf/upload_prefilter/name=protected_files',
'protected_upload_prefilter' );
add_filter( 'acf/prepare_field/name=protected_files', 
'protected_files_field_display' );
function protected_upload_prefilter( $errors ) {

add_filter( 'upload_dir', 'protected_upload_directory' );

return $errors;


function protected_upload_directory( $param ) {

  $folder = '/member-files';

  $param['path'] = WP_CONTENT_DIR . $folder;
  $param['url'] = WP_CONTENT_URL . $folder;
  $param['subdir'] = $folder;
  $param['basedir'] = WP_CONTENT_DIR;
  $param['baseurl'] = WP_CONTENT_URL;

  return $param;


// front-end display

function protected_files_field_display( $field ) {

  // update paths accordingly before displaying link to file
  add_filter( 'upload_dir', 'protected_upload_directory' );

  return $field;


Used with a repeater field, output file links like this:

       // check if the repeater field has rows of data
        if( have_rows('protected_uploads') ):

            // loop through the rows of data
            while ( have_rows('protected_uploads') ) : the_row(); 
            $file_url = get_sub_field('protected_files'); 

           <p><a href="<?php echo $file_url; ?>">
                <?php the_sub_field('date'); ?> Appendix</a>

* EDIT *

Removing this line has no effect on anything at all:

$param['subdir'] = $folder;

* EDIT 2 *

I've tried changing $param to WP_PLUGIN_DIR and WP_PLUGIN_URL. Again, that would show the correct URLs in the back-end (now changed to the /plugins/ directory instead of /uploads/), but curiously, on the front-end all file links point to domain.com/wp-content/uploads/file.pdf

Which confirms that it's set by the upload_dir bit in the second part. So, I've kind of narrowed it down. With what should it be replaced to get the actual upload directory? At this point I'd be ok with even hard-coding the location of the uploaded files.

Answers 1

  • Resolved in a completely different way. Googled this, so technically not my own answer, but does the job:

    // ACF upload prefilter
    function gist_acf_upload_dir_prefilter($errors, $file, $field) {
        // This filter changes directory just for item being uploaded
        add_filter('upload_dir', 'gist_acf_upload_dir');
    // ACF hook, set to field key of your file upload field
    add_filter('acf/upload_prefilter/key=field_5b2b0326ea0e1', 'gist_acf_upload_dir_prefilter');
    // Custom upload directory function, trigger by prefilter
    function gist_acf_upload_dir($param) {
        // Set to whatever directory you want the ACF file field to upload to
        $custom_dir = '/uploads/member-files';
        $param['path'] = WP_CONTENT_DIR . $custom_dir;
        $param['url'] = WP_CONTENT_URL . $custom_dir;
        return $param;

Related Questions