Custom Fields
Re-Envisioned
Support General How to set a upload directory for file_upload

This topic contains 6 replies, has 2 voices, and was last updated by  Anh Tran 11 months, 2 weeks ago.

  • Creator
    Topic
  • #9374

    ComSi
    Participant

    Backstory: Currently working on a Custom Post Type that will need a file uploaded to that post. The file needs to be secured (hidden for the world + only accessed through PHP and not by URL to check if the user has permission).
    Then I’ll create a shortcode that will generate a download button that will serve the file out to the user if he has access to it, or redirect to a page saying he needs to log in or something.

    I’ve used WordPress’ upload_dir filter(*) to actually upload the file in /uploads/secure-dir/example.pdf and that works as expected, the file is added in the correct path.
    Right after uploading, the file_upload metabox template shows me the correct URL to the file (the [edit] link also works correctly), UNTIL I reload the page. Then the template somehow returns /uploads/example.pdf (stripped the “/secure-dir” from the path). Opening the file, or using the edit-link, no longer works.

    My question is how I can best set a custom upload path for the Metabox file_upload?

    (*) https://codex.wordpress.org/Plugin_API/Filter_Reference/upload_dir

Viewing 6 replies - 1 through 6 (of 6 total)
  • Author
    Replies
  • #9381

    Anh Tran
    Keymaster

    Hi,

    The plugin doens’t change the way WP handles the upload process. Probably the ajax part has some issue. Let me see if I can do anything.

    #9416

    Anh Tran
    Keymaster

    Hello,

    I’ve tested with upload_dir filter and it works for Meta Box. However, it’s important to note that the documentation on Codex is not accurate. If you use exactly what in the Codex, e.g.:

    add_filter( 'upload_dir', function ( $param ) {
        $mydir = '/awesome';
        $param['path'] = $param['path'] . $mydir;
        $param['url'] = $param['url'] . $mydir;
    
        return $param;
    } );

    Then it will work.

    However, if you want to move to a new directory other than uploads, you need to change not only path and url, but also basedir and baseurl, like this:

    add_filter( 'upload_dir', function ( $param ) {
        $param['basedir'] = wp_normalize_path( ABSPATH . 'custom-uploads' );
        $param['baseurl'] = home_url( '/custom-uploads' );
        $param['path']    = $param['basedir'];
        $param['url']     = $param['baseurl'];
        $param['subdir']  = '';
    
        return $param;
    } );

    The code above will upload files to custom-uploads folder in the root directory. As you see, basedir and baseurl, subdir are used to set the correct URL of the files.

    Please try that in your case and let me know how it works.

    #9478

    ComSi
    Participant

    Thanks Anh, that example works. A bit too limited for our needs though.
    It gets a lot more complicated since we’re trying to do that only for a specific custom post type, not complete WordPress.

    We basically created a CPT “Downloads” and each post has a file uploaded to it through the file_upload metabox field. This file needs to be uploaded to /wp-content/uploads/secure/ and not /wp-content/uploads/[year]/[month]/ like the rest of time images and files that can be publicly available.

    The files uploaded to this /wp-content/uploads/secure/ directory are being denied through .htaccess so that only PHP can access them, not the browser directly.

    <Files *>
      Deny from all
    </Files>

    In theory.., not that hard. Especially since the file has a correct GUID in the database directly from the start. But after uploading a file and reloading the custom post type page, the above example no longer works without jumping through a whole lot of hoops.
    I think we might have found a way by hooking into all the ajax hooks that are being fired for uploading, viewing and deleting a file to this custom post.

    I’m not sure if we can show you a complete example of what we ended up with because it’s so many hooks tied together. We’ll let you know.

    #9481

    Anh Tran
    Keymaster

    I see. The code that I posted above works for whole website, because that’s the only PHP hook WordPress provides. And it’s site-wide.

    If your CPT doesn’t have any other upload fields, then you can add some PHP checks to make sure the filter runs only for that CPT only. That might work.

    And if you can hook into the ajax process, please share with us. I’m curious how to do that, too.

    #9492

    ComSi
    Participant

    Hello Anh,

    We did it with some action checks in the post. While the ajax-request runs it also runs the ‘upload_dir’ function. So we did it like the code underneed.

    function change_upload_dir( $param ) {
        
        // Ajax request for deleting an uploaded file from MetaBox
        if( isset($_POST['action']) && $_POST['action'] == 'delete-post' ) {
            // Check if CPT is: Downloads
        }
    
        // Ajax request for the list of uploaded files from MetaBox
        elseif( isset($_POST['action']) && $_POST['action'] == 'query-attachments' ) {
            // Check if CPT is: Downloads
        }
    
        // Other actions
        else {
            //Check if post is cpt:bestanden
            if( isset($post->post_type) && $post->post_type == 'Downloads' ) {
            } 
        }
        
    }
    add_filter( 'upload_dir', 'change_upload_dir' );
    
    #9497

    Anh Tran
    Keymaster

    That’s cool. Is the global $post object is available and set to the being edited post inside the filter?

Viewing 6 replies - 1 through 6 (of 6 total)

You must be logged in to reply to this topic.