Adding File Extensions to Attachment Page Permalinks

Great question! I’ve been thinking about this myself and your question prompted me to dig into it.

There is a filter wp_insert_attachment_data than can be used to fix the slug name for uploaded files. It is called for attachments shortly before the attachment is inserted into the database in post.php.

The following sample will append the mime type to the slug name, for example image-jpg will be added to a jpeg image title.

    /**
     * Filter attachment post data before it is added to the database
     *  - Add mime type to post_name to reduce slug collisions
     *
     * @param array $data    Array of santized attachment post data
     * @param array $postarr Array of unsanitized attachment post data
     * @return $data, array of post data
     */
    function filter_attachment_slug($data, $postarr)
    {
        /**
         * Only work on attachment types
         */
        if ( ! array_key_exists( 'post_type', $data ) || 'attachment' != $data['post_type'] )
            return $data;

        /**
         * Add mime type to the post title to build post-name
         */
        $post_title = array_key_exists( 'post_title', $data ) ? $data['post_title'] : $postarr['post_title'];
        $post_mime_type = array_key_exists( 'post_mime_type', $data ) ? $data['post_mime_type'] : $postarr['post_mime_type'];
        $post_mime_type = str_replace( "https://wordpress.stackexchange.com/", '-', $post_mime_type );
        $post_name = sanitize_title( $post_title . '-' . $post_mime_type );

        /**
         * Generate unique slug for post name
         */
        $post_ID = array_key_exists( 'ID', $data ) ? $data['ID'] : $postarr['ID'];
        $post_status = array_key_exists( 'post_status', $data ) ? $data['post_status'] : $postarr['post_status'];
        $post_type = array_key_exists( 'post_type', $data ) ? $data['post_type'] : $postarr['post_type'];
        $post_parent = array_key_exists( 'post_parent', $data ) ? $data['post_parent'] : $postarr['post_parent'];

        $post_name = wp_unique_post_slug( $post_name, $post_ID, $post_status, $post_type, $post_parent );
        $data['post_name'] = $post_name;

        return $data;
    }

    /**
     * Adjust slug for uploaded files to include mime type
     */
    add_filter( 'wp_insert_attachment_data', 'filter_attachment_slug', 10, 2 );