Sending av multipart/formdata med jQuery.ajax
Jeg'har et problem med å sende en fil til et PHP-script på serversiden ved hjelp av jQuery's ajax-funksjon.
Det er mulig å hente fil-listen med $('#fileinput').attr('files')
, men hvordan er det mulig å sende disse dataene til serveren? Den resulterende matrisen ($_POST
) på serversidens php-skript er 0 (NULL
) når du bruker file-input.
Jeg vet at det er mulig (selv om jeg ikke fant noen jQuery-løsninger før nå, bare Prototye-kode (http://webreflection.blogspot.com/2009/03/safari-4-multiple-upload-with-progress.html)).
Dette ser ut til å være relativt nytt, så vær så snill å ikke nevne at filopplasting er umulig via XHR/Ajax, for det fungerer definitivt.
Jeg trenger funksjonaliteten i Safari 5, FF og Chrome ville vært fint, men er ikke avgjørende.
Min kode for nå er:
$.ajax({
url: 'php/upload.php',
data: $('#file').attr('files'),
cache: false,
contentType: 'multipart/form-data',
processData: false,
type: 'POST',
success: function(data){
alert(data);
}
});
Fra og med Safari 5/Firefox 4 er det enklest å bruke klassen
FormData
:Nå har du et
FormData
-objekt som er klart til å sendes sammen med XMLHttpRequest.Det er viktig at du setter alternativet
contentType
tilfalse
, slik at jQuery ikke legger til enContent-Type
header for deg, ellers vil grensestrengen mangle. Du må også laprocessData
-flagget være satt til false, ellers vil jQuery prøve å konvertereFormData
til en streng, noe som vil mislykkes.Du kan nå hente filen i PHP ved hjelp av:
(Det finnes bare én fil,
file-0
, med mindre du har angitt attributtetmultiple
på filinndataene, i så fall vil tallene øke for hver fil).Bruke FormData-emulering for eldre nettlesere.
Gjenopprette FormData fra et eksisterende skjema.
I stedet for å iterere filene manuelt, kan FormData-objektet også opprettes med innholdet i et eksisterende skjemaobjekt:
Bruk en PHP-innfødt array i stedet for en teller.
Bare navngi filelementene dine på samme måte og avslutt navnet i parentes:
$_FILES['file']
blir da en matrise som inneholder filopplastingsfeltene for hver opplastede fil. Jeg anbefaler faktisk dette fremfor min opprinnelige løsning, da det er enklere å iterere over.Ville bare legge til litt til Raphaels gode svar. Slik får du PHP til å produsere de samme
$_FILES
, uavhengig av om du bruker JavaScript til å sende.HTML-skjema:
PHP produserer denne
$_FILES
når den sendes inn uten JavaScript:Hvis du gjør progressiv forbedring ved hjelp av Raphael's JS for å sende inn filene...
... slik ser PHP's
$_FILES
-array ut etter at du har brukt JavaScript til å sende inn:Det er en fin matrise, og faktisk det noen forvandler
$_FILES
til, men jeg synes det er nyttig å jobbe med de samme$_FILES
, uavhengig av om JavaScript ble brukt til å sende inn. Så her er noen mindre endringer i JS:(redigering 14. april 2017: Jeg fjernet skjemaelementet fra konstruktøren av FormData() - det fikset koden i Safari).
Denne koden gjør to ting.
input
-navnattributtet automatisk, noe som gjør HTML-en mer vedlikeholdbar. Så lengeform
har klassen putImages, blir alt annet tatt hånd om automatisk. Det vil si atinput
ikke trenger å ha noe spesielt navn.Med disse endringene produserer innsending med JavaScript nå nøyaktig samme
$_FILES
-array som innsending med enkel HTML.Jeg bygde nettopp denne funksjonen basert på noe informasjon jeg leste.
Bruk den som å bruke
.serialize(), i stedet bare sett
.serializefiles();`.Fungerer her i testene mine;