Why is $_REQUEST an empty array in admin-ajax.php?

Here’s the problem:

    var formData = new FormData();
    formData.append( "userfile", $(this)[0].files[0] );
    formData.append( "action", "vibesoft_files_upload" );
    formData.append( "_wpnonce", vbsoft.nonce_upload );

    console.log( formData );

    $.ajax({
        type: "post",
        url: vbsoft.ajax_url,
        data: formData,

Specifically:

    var formData = new FormData();

Nowhere in the jQuery documentation does it say that data accepts a FormData object for the data parameter:

data Type: PlainObject or String or Array Data to be sent to the
server. It is converted to a query string, if not already a string.
It’s appended to the url for GET-requests. See processData option to
prevent this automatic processing. Object must be Key/Value pairs. If
value is an Array, jQuery serializes multiple values with same key
based on the value of the traditional setting (described below).

https://api.jquery.com/jQuery.ajax/

The solution is to instead use an object, e.g.:

var formData = {
    "userfile": $(this)[0].files[0],
    "action": "vibesoft_files_upload",
    "_wpnonce": vbsoft.nonce_upload
};

Keep in mind that if you’d used the much easier REST API, and specified the fields required, the API would have told you point blank what the problem was and which fields were missing. The REST API is much easier to use, with far fewer gotchas and hangups to trip over

So much so, there’s already a core endpoint that might be able to do what you’re trying to do, see https://developer.wordpress.org/rest-api/reference/media/