Cum pot Importa / Încărca Fișiere cu jQuery AJAX?

1 nov. 2012, 15:08:14
Vizualizări: 66.2K
Voturi: 0

Întâmpin frecvent o problemă în a trimite fișiere prin AJAX astfel încât funcția ajax de pe server să poată procesa datele. Cum pot face ca $_FILES să fie transmis la fel ca în cazul acțiunii implicite (incorporată în elementele formularului)?

Formular HTML

<form id="frmImport" name="frmImport" method="post" enctype="multipart/form-data" >
    <input id="file_import" name="importData" type="file" />
    <br/>
    <button id="btn_import" type="submit" >Import</button>
</form>

JavaScript

    jQuery(document).ready(function($) {
    //Aceasta este deja configurată și trimisă de pe partea serverului și
    // este folosită pentru a preveni utilizatorii neautorizați să încarce date.
    var importnonce = "3x4mpl3f4k3n0nc3"; 

    $('#frmImport').submit(function(e) {
        e.preventDefault();

        // VERIFICĂ DACĂ EXISTĂ ERORI AICI.
        // DACĂ EXISTĂ ERORI, RETURNEAZĂ FALSE PENTRU A OPRI OPERAȚIUNILE.

        var formData = new FormData();
        formData.append('action', 'ajax_handler_import');
        formData.append('_ajax_nonce', importNonce);

        // Problema apare aici. PHP primește un string '[object FormData]'.
        var importFiles = $('#file_import')[0].files;
        formData.append('uploadFiles', importFiles);

        jQuery.ajax({
            url: ajaxurl,
            type: 'POST',
            cache: false,
            contentType: false,
            processData: false,

            data: formData,

            beforeSend: function(jqXHR, settings) {
                console.log("Nu am intrat încă în partea de server.");
            },
            dataFilter: function(data, type) {
                // Folosit pentru a analiza datele și eventual pentru a verifica erorile.
                console.log("String JSON returnat de la partea de server.");
            },
            success: function(data, textStatus, jqXHR) {
                console.log("Înapoi de la partea server!");
                // Verificarea erorilor care ar fi putut fi prinse pe partea de server și care
                // în mod normal nu ar fi afișate în funcția de eroare Ajax.
                if (data.msg != 'success') {
                    alert(data.error);
                }
            },
            error: function(jqXHR, textStatus, errorThrown) {
                console.log("A apărut o eroare JS.");
            },
            complete: function(jqXHR, textStatus) {
                console.log("Ajax s-a finalizat.");
            }
        });

        return false;
    });
});

PHP Server/Handler

<?php
class server {
    function ajax_import_handler() {
        check_ajax_referer("ajax_handler_import");

        $rtnData = new stdClass();
        $rtnData->msg = 'success'; //Pentru semnalarea erorilor Server
        $rtnData->error = ''; //Pentru afișarea mesajelor de eroare personalizate sau utilizarea metodei try/catch

        //Execută operațiuni
        foreach ($_FILES as $key => $value) {
            //OBȚINE CONȚINUTUL FIȘIERULUI
            $file_array[$key] = json_decode(file_get_contents($value['tmp_name']));
        }

        // Execută mai multe operațiuni cu fișierul(ele).

        // Adaugă informații în $rtnData.

        echo json_encode($rtnData);
    }
}
?>
0
Toate răspunsurile la întrebare 3
2

Nu am încercat, dar cred că trebuie să adaugi obiectul FormData direct ca parametru data. Ceva de genul:

    var ajaxData = new FormData();

    ajaxData.append( 'action', 'ajax_handler_import' );
    ajaxData.append( '_ajax_nonce', importNonce );
    // sau poate sări peste nonce pentru moment

    jQuery.each($('#fileImportData')[0].files, function(i, file) {
        ajaxData.append('file-'+i, file);
    });

Restul codului tău rămâne la fel

1 nov. 2012 15:33:21
Comentarii

Îmi pare rău că nu am răspuns mai devreme... Încercam să termin un proiect și m-am gândit să revin când voi avea mai multe cunoștințe pe acest subiect. Mulțumesc pentru soluția oferită, nu știam că adăugarea obiectului FormData într-un alt obiect va crea probleme și rămăsesem fără idei. Se pare că era o problemă simplă xP. Lecția învățată aici: evită obiectele mixte.

EkoJR EkoJR
1 dec. 2012 11:44:29

Ca să nu mai menționăm că acest lucru nu va funcționa pe IE9 și versiunile mai vechi de IE.

Arda Arda
3 nov. 2015 17:32:49
2

Ajax în sensul tradițional este XMLHttpRequest, care nu permite codificarea și trimiterea fișierelor locale către un server.

Modalitățile obișnuite de a încărca prin mijloace "ajax" sunt fie utilizarea unui fișier Flash swf pentru a gestiona încărcarea pe aceeași pagină, fie utilizarea unui formular care are ca țintă un iframe invizibil de 1x1.

Aici este o întrebare foarte asemănătoare cu un răspuns bun pentru a vedea cum poți face asta

1 nov. 2012 15:51:04
Comentarii

Da, am parcurs recent acel Q/A. Din păcate, nu sunt familiarizat cu Flash și am încercat să evit adăugarea de plugin-uri cât de mult posibil. Am încercat în principal să urmez metoda Ajax din WordPress, dar din câte am aflat, transmiterea simplă prin ajax este restricționată/limitată de browsere. Referindu-mă în principal la acest Q/A care m-a condus la Obiectele FormData, care afirmă că este posibil dacă browserul folosit le suportă.

EkoJR EkoJR
2 nov. 2012 10:45:07

Se pare că poți folosi propriile metode pentru a transmite datele fișierelor către o funcție AJAX, în loc să te bazezi pe un plugin JS. În mare parte, Obiectele FormData (cum s-a menționat mai sus), se ocupă de acest lucru cu operațiuni XMLHttpRequest Level 2 (după cum înțeleg eu acum), și sunt acceptate de toate browserele majore acum. M-am gândit că va fi doar o chestiune de timp după apariția HTML5. Cu toate acestea, utilizarea plUpload este o recomandare posibilă pentru datele fișierelor mari.

EkoJR EkoJR
1 dec. 2012 11:54:53
0

Iată soluția pe care am reușit să o găsesc și observ destul de multe greșeli comune care au fost făcute.

  • Fișierele nu erau atașate corect în JS.
  • AJAX dataFilter: function() putea fi înlocuit cu dataType: 'json'.
  • JS submit nu are nevoie să returneze false pentru a opri acțiunea formularului.
    • Poate fi înlocuit cu event.stopPropagation() și e.preventDefault().
    • Adăugați un action gol în HTML.
  • Funcția PHP pentru AJAX nu se termina cu die().

HTML

<form id="form_import" name="form_import" method="post" enctype="multipart/form-data" action >
    <input id="file_import" name="import_data" type="file" />
    <br/>
    <button id="btn_import" type="submit" >Import</button>
</form>

JavaScript

jQuery(document).ready(function($){
    // Fișierele PHP pot returna un Nonce. Acest lucru localizează scripturile.
    var importNonce = localizedData.import_nonce;

    $('#form_import').submit( function( event ) {
        event.stopPropagation(); // Oprește acțiunile implicite
        event.preventDefault(); // Oprește complet acțiunile implicite

        var formData = new FormData();
        var importFiles = $('#file_import')[0].files;

        // Pentru FIECARE fișier, adaugă în formData.
        // NOTĂ: Adăugarea tuturor fișierelor din importFiles nu funcționează bine cu PHP.
        jQuery.each( importFiles, function( index, value ) {
            var name = 'file_' + index;
            formData.append( name, value )
        });

        formData.append( 'action', 'ajax_file_import' );
        formData.append( '_ajax_nonce', importNonce );

        jQuery.ajax({
            url: ajaxurl,
            type: 'POST',
            data: formData,
            cache: false,
            dataType: 'json', // Înlocuiește dataFilter: function() && JSON.parse( data ).
            processData: false, // Nu procesa fișierele
            contentType: false, // Setează content type la false deoarece jQuery va spune serverului că este o cerere de tip query string

            beforeSend: function( jqXHR, settings ){
                // (OPȚIONAL) Concept alternativ pentru AJAX.
                // Elimină vechiul IFrame dacă există.
                var element = document.getElementById('import_IF');
                if ( element !== null ){
                    element.parentNode.removeChild( element );
                }
                // SFÂRȘIT (OPȚIONAL).
            },
            success: function( data, textStatus, jqXHR ) {
                console.log( 'Răspuns de la funcția/metoda PHP AJAX.' );

                // Manipulează datele din data.values

                // (OPȚIONAL) Concept alternativ pentru AJAX.
                // Necesar pentru descărcare în AJAX.
                var paramStr = '';
                paramStr += '?_ajax_nonce=' + data._ajax_nonce;
                paramStr += '&action='      + data.action;
                paramStr += '&filename='    + data.filename;

                var elemIF = document.createElement("iframe");
                elemIF.id = 'import_IF'
                elemIF.style.display = "none";
                elemIF.src = ajaxurl + paramStr;

                document.body.appendChild(elemIF);
                elemIF.parentNode.removeChild(elemIF);
                // SFÂRȘIT (OPȚIONAL).
            },
            complete: function(jqXHR, textStatus){
                console.log( 'AJAX este complet.' );

                // (OPȚIONAL) Concept alternativ pentru AJAX.
                // Curăță IFrame.
                var element = document.getElementById('import_IF');
                if ( element !== null ){
                    element.parentNode.removeChild( element );
                }
                // SFÂRȘIT (OPȚIONAL).
            }
        });// Sfârșit AJAX.
    });// Sfârșit .submit().
});

PHP

<?php
class server {
    public function __construct() {
        // Exemplu pentru adăugarea de scripturi.
        add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_example' ) );
        add_action( 'wp_ajax_ajax_file_import', array( $this, 'ajax_import_example' ) );
    }

    public function enqueue_example() {
        wp_register_script(
            'example-js',
            FILE_URL,
            array(),
            VERSION,
            false
        );
        wp_enqueue_script( 'example-js' );

        $data = array(
            'import_nonce'  => wp_create_nonce( 'ajax_file_import_nonce' ),
        );

        wp_localize_script( 'example-js', 'localizedData', $data );
    }

    public function ajax_import_example() {
        check_ajax_referer( 'ajax_file_import_nonce' );

        $raw_content = array();
        $i = 0;
        while ( isset( $_FILES[ 'file_' . $i ] ) ) {
            $file_arr = $_FILES[ 'file_' . $i ];
            $file_content = file_get_contents( $file_arr['tmp_name'] );
            $raw_content[]  = json_decode( $file_content );
            $i++;
        }

        $new_data = array();
        // Manipulează datele noi.
        update_option( 'example_database', $new_data );

        // (OPȚIONAL) Adaugă date pentru returnare în AJAX Success
        $rtn_data = array(
            'action'               => 'apl_import',
            '_ajax_nonce'          => wp_create_nonce( 'alt_ajax' ),
        );
        echo json_encode( $rtn_data );
        // SFÂRȘIT (OPȚIONAL).

        die();
    }
}
?>
2 iul. 2017 10:41:15