I am using wp_upload_bits()
to copy an obtained remote image…
$upload = wp_upload_bits($file, '', wp_remote_retrieve_body( $get ));
Image source example: https://logo.clearbit.com/starcomww.com
The following code seems to obtain the image well enough:
$get = wp_remote_get( $image_url );
$type = wp_remote_retrieve_header( $get, 'content-type' );
$file
(name of file) is set at eg. starcom-mediavest-group.png
So I see how wp_upload_bits($file
… would set the filename.
But I don’t see how to add the image to a subdirectory of uploads
– specifically called uploads/org_logos
then wp_upload_bits
will strip out the slash, believing it to be a non-safe file character, leading to the incorrect file org_logosstarcom-mediavest-group.png
being placed in the main uploads
folder. It really wants to put it in uploads
!
How do I get the image in a subfolder?
I’m aware of the PHP function move_uploaded_file
– but I’m concerned that this would lose any references for a file I’ll still need to attach to the Media Library. Regardless, I’m not having much luck moving it with this anyway…
// Move it
$thefile = $upload['file'];
$upload_dir = wp_upload_dir();
$newfolder = $upload_dir['basedir'].'/org_logos';
move_uploaded_file($thefile, $newfolder);
wp_upload_bits()
uses wp_upload_dir()
which fires the upload_dir
filter allowing you to modify the upload directory’s path, sub-directory and URL.
So you can use that filter to “force” wp_upload_bits()
to use a custom path by doing something like:
// Demo to get the image data.
$url="https://logo.clearbit.com/starcomww.com";
$content = file_get_contents( $url );
$_filter = true; // For the anonymous filter callback below.
add_filter( 'upload_dir', function( $arr ) use( &$_filter ){
if ( $_filter ) {
$folder="/org_logos"; // No trailing slash at the end.
$arr['path'] .= $folder;
$arr['url'] .= $folder;
$arr['subdir'] .= $folder;
}
return $arr;
} );
$filename = wp_basename( $url ) . '.png';
$ret = wp_upload_bits( $filename, null, $content );
var_dump( $ret ); // For testing.
$_filter = false; // Disables the filter.
Or you can use a named callback:
function my_org_logos_upload_dir( $arr ) {
$folder="/org_logos"; // No trailing slash at the end.
$arr['path'] .= $folder;
$arr['url'] .= $folder;
$arr['subdir'] .= $folder;
return $arr;
}
// Demo to get the image data.
$url="https://logo.clearbit.com/starcomww.com";
$content = file_get_contents( $url );
add_filter( 'upload_dir', 'my_org_logos_upload_dir' );
$filename = wp_basename( $url ) . '.png';
$ret = wp_upload_bits( $filename, null, $content );
var_dump( $ret ); // For testing.
remove_filter( 'upload_dir', 'my_org_logos_upload_dir' );
UPDATE
(In reply to your comments)
So, as a filter on wp_upload_dir()
, that would apply to any file
getting uploaded via wp_upload_dir()
, is that right?
Yes, it would.
But the issue can be prevented by adding/enabling the filter only when you call wp_upload_bits()
and that you want it to use your custom upload path, and then remove/disable the filter after it’s applied — to prevent the upload path from being changed when wp_upload_dir()
is called from other functions or code.
And for that reason, these are my approaches as you have seen in the original answer:
// First variant of the code - using an anonymous function.
$_filter = true; // enables the filter
$_filter = false; // disables the filter
// Second variant of the code - using a named function.
remove_filter( 'upload_dir', 'my_org_logos_upload_dir' ); // enables the filter
add_filter( 'upload_dir', 'my_org_logos_upload_dir' ); // disables the filter
should the second property of wp_insert_attachment()
be $filename
,
$content
or some property of $ret[here]
?
The second parameter of the wp_insert_attachment()
function is the full absolute path to the file that’s to be attached to the post.
And on success, wp_upload_bits()
returns an array with file
being one of the keys, where the value is the full absolute path of the file that was saved by wp_upload_bits()
. (You can check the function’s reference or this note for the other keys.)
So the answer is $ret['file']
:
wp_insert_attachment( array(...), $ret['file'] );