Cum pot Importa / Încărca Fișiere cu jQuery AJAX?
Î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);
}
}
?>

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

Î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.

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

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ă.

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.

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 cudataType: 'json'
. - JS submit nu are nevoie să returneze false pentru a opri acțiunea formularului.
- Poate fi înlocuit cu
event.stopPropagation()
șie.preventDefault()
. - Adăugați un action gol în HTML.
- Poate fi înlocuit cu
- 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();
}
}
?>
