Make attachment pages require a base url

If I upload an image with the filename 8.jpg then the permalink becomes http://www.example.com/8 — which I really don’t want. How can I make attachments use their mime type as a base for the url? http://example.com/image/8?

add_action('init', function(){
    add_rewrite_endpoint( 'media', EP_PERMALINK | EP_ATTACHMENT| EP_PAGES  );
    flush_rewrite_rules(true);
} );

I’m not really sure how endpoints work but I can turn /media/8 into a post…

Solutions Collecting From Web of "Make attachment pages require a base url"

Endpoints are for adding extra query vars to existing routes, I think you just want a vanilla rewrite rule here:

function wpd_media_image_rewrite_rule() {
    add_rewrite_rule(
        '^image/([^/]*)/?',
        'index.php?post_type=attachment&name=$matches[1]',
        'top'
    );
}
add_action( 'init', 'wpd_media_image_rewrite_rule' );

You might want to loop over valid mime-types there and add a rule for each. You also need to flush rewrites for this to start working, but don’t use flush_rewrite_rules on init like in your example above. Rules should only be flushed when they change. A quick way to flush them is to just visit the permalinks settings page.

You’ll also need to filter at least attachment_link to output the correct URL for unattached media, like:

function wpd_media_image_att_link( $link, $post_id ){
    $post = get_post( $post_id );
    if( 0 == $post->post_parent ){
        $link = home_url( user_trailingslashit( 'image/' . $post->post_name ) );
    }
    return $link;
}
add_filter( 'attachment_link', 'wpd_media_image_att_link', 10, 2 );

Here we check if the attachment doesn’t have a parent, because if it’s attached to a post, it would be a child of the parent post. You could also check mime-type here and make the image/ part dynamic according to type.

There’s also the wp_get_attachment_link function which may need a filter, if that’s used in the template somewhere. I don’t think core admin uses that function anywhere though, but I may be wrong.