Support Forum
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
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.
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.
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.
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.
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' );
That's cool. Is the global $post
object is available and set to the being edited post inside the filter?