Come Importare/Caricare File con jQuery AJAX?
Continuo a incontrare un problema nell'aggiungere i file tramite AJAX in modo che la funzione ajax del server possa elaborare i dati. Come posso far passare $_FILES allo stesso modo della action predefinita (incorporata negli elementi del form)?
Form 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" >Importa</button>
</form>
JavaScript
jQuery(document).ready(function($) {
// Questo è già configurato e inviato dal lato server, e viene
// utilizzato per impedire agli utenti non autorizzati di caricare dati.
var importnonce = "3x4mpl3f4k3n0nc3";
$('#frmImport').submit(function(e) {
e.preventDefault();
// CONTROLLA SE CI SONO ERRORI QUI.
// SE ESISTONO ERRORI, RITORNA FALSE PER TERMINARE LE OPERAZIONI.
var formData = new FormData();
formData.append('action', 'ajax_handler_import');
formData.append('_ajax_nonce', importNonce);
// Il problema si verifica qui. PHP riceve una stringa '[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("Non ancora entrato lato server.");
},
dataFilter: function(data, type) {
// Utilizzato per analizzare i dati e possibilmente controllare gli errori.
console.log("Stringa JSON restituita dal lato server.");
},
success: function(data, textStatus, jqXHR) {
console.log("Ritorno dal lato server!");
// Controllo degli errori che potrebbero essere stati rilevati sul lato server
// che normalmente non verrebbero visualizzati nella funzione Ajax di errore.
if (data.msg != 'success') {
alert(data.error);
}
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("Si è verificato un errore JS.");
},
complete: function(jqXHR, textStatus) {
console.log("Ajax è terminato.");
}
});
return false;
});
});
PHP Server/Handler
<?php
class server {
function ajax_import_handler() {
check_ajax_referer("ajax_handler_import");
$rtnData = new stdClass();
$rtnData->msg = 'success'; // Per segnalare errori del Server
$rtnData->error = ''; // Per visualizzare messaggi di errore personalizzati o utilizzare il metodo try/catch
// Esegui operazioni
foreach ($_FILES as $key => $value) {
// OTTIENI IL CONTENUTO DEL FILE
$file_array[$key] = json_decode(file_get_contents($value['tmp_name']));
}
// Esegui altre operazioni con i file.
// Aggiungi elementi a $rtnData.
echo json_encode($rtnData);
}
}
?>

Non ho provato ma penso che tu debba aggiungere l'oggetto FormData
direttamente come parametro data
. Qualcosa come questo:
var ajaxData = new FormData();
ajaxData.append( 'action', 'ajax_handler_import' );
ajaxData.append( '_ajax_nonce', importNonce );
// oppure forse salta il nonce per ora
jQuery.each($('#fileImportData')[0].files, function(i, file) {
ajaxData.append('file-'+i, file);
});
Il resto del tuo codice rimane come è

Scusa se non ho risposto prima... Stavo cercando di finire un progetto e ho pensato di tornare quando avrò più conoscenza sull'argomento. Grazie per aver fornito la soluzione, non sapevo che aggiungere l'oggetto FormData a un oggetto potesse causare problemi, e stavo finendo le idee. Immaginavo fosse un problema semplice xP. La lezione imparata qui: evita oggetti misti.

Ajax nel senso tradizionale è XMLHttpRequest, che non consente di codificare e inviare file locali a un server.
I modi comuni per effettuare il caricamento tramite mezzi "ajax", sono utilizzare un file Flash swf per gestire il caricamento sulla stessa pagina, oppure utilizzare un modulo che ha come target un iframe invisibile 1x1.
Ecco una domanda molto simile con una buona risposta per vedere come puoi farlo

Sì, stavo esaminando quel Q/A di recente. Sfortunatamente, non ho familiarità con Flash e ho cercato di evitare l'aggiunta di plugin quando possibile. Ho principalmente seguito il metodo Ajax di WordPress, ma da quello che ho scoperto, passare semplicemente i dati ad Ajax è limitato/ristretto dai browser. Principalmente riferendomi a questo Q/A mi ha portato agli oggetti FormData che dicono essere possibili se il browser utilizzato li supporta.

Si scopre che puoi utilizzare i tuoi metodi per passare i dati dei file a una funzione AJAX invece di affidarti a un plugin JS. Per la maggior parte, gli oggetti FormData (come menzionato sopra), gestiscono questo con operazioni XMLHttpRequest Level 2 (per come lo capisco attualmente), ed è supportato da tutti i principali browser ora. Immaginavo che sarebbe stata questione di tempo dopo l'uscita di HTML5. Tuttavia, l'uso di plUpload è una possibile raccomandazione per file di grandi dimensioni.

Ecco la soluzione che sono riuscito a trovare, e in realtà vedo diversi errori comuni che sono stati commessi.
- I file non venivano aggiunti correttamente in JS.
- L'AJAX
dataFilter: function()
poteva essere sostituito condataType: 'json'
. - Il submit JS non ha bisogno di restituire false per fermare l'azione del form.
- Poteva essere sostituito con
event.stopPropagation()
ee.preventDefault()
. - Aggiungere un'azione vuota al form in HTML.
- Poteva essere sostituito con
- La funzione PHP per AJAX non terminava con 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" >Importa</button>
</form>
JavaScript
jQuery(document).ready(function($){
// I file PHP potrebbero restituire un Nonce. Questo però localizza gli script.
var importNonce = localizedData.import_nonce;
$('#form_import').submit( function( event ) {
event.stopPropagation(); // Ferma le azioni predefinite
event.preventDefault(); // Blocca completamente le azioni predefinite
var formData = new FormData();
var importFiles = $('#file_import')[0].files;
// Per OGNI file, aggiungi a formData.
// NOTA: Aggiungere semplicemente tutti i importFiles non si traduce bene in 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', // Questo sostituisce dataFilter: function() && JSON.parse( data ).
processData: false, // Non elaborare i file
contentType: false, // Imposta il content type a false poiché jQuery dirà al server che è una richiesta di query string
beforeSend: function( jqXHR, settings ){
// (OPZIONALE) Concetto alternativo AJAX.
// Rimuove il vecchio IFrame se presente.
var element = document.getElementById('import_IF');
if ( element !== null ){
element.parentNode.removeChild( element );
}
// FINE (OPZIONALE).
},
success: function( data, textStatus, jqXHR ) {
console.log( 'Risposta dalla funzione/metodo PHP AJAX.' );
// Fai qualcosa con data.values
// (OPZIONALE) Concetto alternativo AJAX.
// Necessario per il download in 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);
// FINE (OPZIONALE).
},
complete: function(jqXHR, textStatus){
console.log( 'AJAX completato.' );
// (OPZIONALE) Concetto alternativo AJAX.
// Pulizia IFrame.
var element = document.getElementById('import_IF');
if ( element !== null ){
element.parentNode.removeChild( element );
}
// FINE (OPZIONALE).
}
});// Fine AJAX.
});// Fine .submit().
});
PHP
<?php
class server {
public function __construct() {
// Esempio per aggiungere script.
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();
// Fai qualcosa con i nuovi dati.
update_option( 'example_database', $new_data );
// (OPZIONALE) Aggiungi dati da restituire ad AJAX Success
$rtn_data = array(
'action' => 'apl_import',
'_ajax_nonce' => wp_create_nonce( 'alt_ajax' ),
);
echo json_encode( $rtn_data );
// FINE (OPZIONALE).
die();
}
}
?>
