1

I'm trying to upload files using AJAX and I'm hooking in my functions so they get called within admin-ajax. I can't get it to work tough, and I didn't have any idea what was wrong or where to look at all. I narrowed it down, however, by modifying admin-ajax.php a little bit:

// Require an action parameter
if ( empty( $_REQUEST['action'] ) ) {
    $response = array(
        'error' => 'no action parameter',
        'req' => var_export( $_REQUEST, true )
    );
    wp_send_json( $response );
    wp_die( '0', 400 );
}

My AJAX request has dataType: 'json' in it, so my success function does get called(if I remove the $response declaration and the call to wp_send_json, the error one gets called, returning the entire page as a response with the statusText being "parsererror").

Anyway, here's my AJAX script:

    $( '#user-file' ).change( function( event ) {
        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,
            contentType: "multipart/form-data",
            processData: false,
            dataType: 'json',

            success: function( data ) {
                if ( data.error != 'none' ) {
                    console.log( 'Error: ' + data.error );
                    console.log( 'Request: ' + data.req );
                    return;
                }

It's not the entire function, which is wrapped inside (function($) { ... })(jQuery); so I can use $ instead of jQuery. The console.log( 'Request: ' + data.req ); outputs:

Request: array(
)

I also tried outputting the $_POST and $_FILES and they, too, are empty arrays. If I send them back using(instead of the JSON return):

var_dump( $_REQUEST );
exit;

I get array(0) {} back in the console.

So, yeah, I have no idea why am I getting an empty array...

  • 1
    I'd advise against using REQUEST, it contains a lot more than you think, including the contents of _COOKIE and _SESSION, use GET and POST explicitly for security reasons. Also have you considered using a REST API endpoint? The API is much more straight forward and you even get a pretty URL at the end – Tom J Nowell Mar 20 '18 at 0:45
  • @TomJNowell The $_REQUEST is what admin-ajax.php uses, so I didn't want to modify it, but I will try it and will also look into REST API. – Tarik Druskic Mar 20 '18 at 0:50
  • Can you post your answer as an answer rather than an edit of your question? – Tom J Nowell Mar 20 '18 at 14:03
  • use request if you know what it does and know why it could be a security issue otherwise just don't use it. it doesnt mean any one who uses it is doing it wrong of course. – Joel M Mar 21 '18 at 4:00
1

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/

0

Solved it!

I ended up using the FormData object and changing the $.ajax call to:

$.ajax({
            method: 'post',
            processData: false,
            contentType: false,
            cache: false,
            data: form_data,
            enctype: 'multipart/form-data',
            url: custom.ajaxURL,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.