WordPress file upload

WordPress has it’s own way of handling file uploads, so it’s best to follow their lead on that. It does do some file validation, but if you want to be restrictive with MIME types I’d keep the code you originally have,

Here’s the code that can replace your second block though to actually upload the file (modified from an example in the Codex as linked above):

// Load in the file handler
    if ( ! function_exists( 'wp_handle_upload' ) ) {
    require_once( ABSPATH . 'wp-admin/includes/file.php' );
    }

// Change your upload directory
function wpse_271103_upload_dir(){
    return PLUGIN_DIR . '/uploads/';
}

// Register our path override.
add_filter( 'upload_dir', 'wpse_271103_upload_dir' );

// Set where to get the file from
$uploadedfile = $_FILES["attach"]["tmp_name"];

// Do the file move
$movefile = wp_handle_upload( $uploadedfile );

// Set everything back to normal.
remove_filter( 'upload_dir', 'wpse_271103_upload_dir' );

// Return an error if it couldn't be done
if ( ! $movefile || isset( $movefile['error'] ) ) {

    echo $movefile['error'];
}