Bestanden uploaden met AJAX

Ik kan niet het einde bereiken van de leuke dingen die je kunt doen met nieuwe webtechnologieën. Vandaag laat ik je zien hoe je iets kunt doen dat tot voor kort het einde was van de ongekende ontwikkeling: uploaden van bestanden via AJAX.

Oh, natuurlijk zijn er hacks geweest; maar als je bent zoals ik, en je vies voelt elke keer dat je typt iframe, je gaat dit erg leuk vinden. Ga met me mee na de sprong!

Op zoek naar een snelle oplossing?

Als u op zoek bent naar een snelle oplossing, is er een grote verzameling scripts en toepassingen voor het uploaden van bestanden bij Envato Market.я

Deze HTML5-uploader is bijzonder handig: u kunt bestanden eenvoudig toevoegen door ze te slepen en neer te zetten of door erop te klikken. Alle bestanden worden geüpload via AJAX of kunnen in een formulier worden toegevoegd en bestanden kunnen worden hernoemd voordat ze worden geüpload. Een geweldige, snelle oplossing als dat is wat u zoekt!


Waarom krijgen we het slechte nieuws niet mee??

Dit werkt niet in elke browser. Echter, met een aantal progressieve verbeteringen (of wat dan ook het huidige buzzword is), zullen we een uploadpagina hebben die meteen weer werkt naar IE6 (hoewel zonder de AJAXy-bits).

Onze AJAX-upload werkt zo lang als FormData is beschikbaar; anders krijgt de gebruiker een normale upload.

Er zijn drie hoofdcomponenten voor ons project.

  • De meerdere attribuut op het bestand invoer element.
  • De FileReader object van de nieuwe File API.
  • De FormData object van XMLHttpRequest2.

Wij gebruiken de meerdere attribuut om de gebruiker toe te staan ​​om meerdere bestanden te selecteren om te uploaden (uploaden van meerdere bestanden zal normaal werken, zelfs als FormData is niet beschikbaar). Zoals je zult zien, FileReader stelt ons in staat om de gebruikersminiaturen te tonen van de bestanden die ze uploaden (we verwachten afbeeldingen).

Geen van onze drie functies werkt in IE9, dus alle IE-gebruikers krijgen een normale uploadervaring (hoewel ik begrijp dat ondersteuning voor 'FileReader' beschikbaar is in IE10 Dev Preview 2). FileReader werkt niet in de nieuwste versie van Safari (5.1), dus krijgen ze geen thumbnails, maar krijgen ze de AJAX-upload en het bevestigingsbericht. Eindelijk, Opera 10.50 heeft FileReader ondersteuning maar niet FormData ondersteuning, zodat ze miniaturen krijgen, maar normale uploads.

Met dat uit de weg, laten we coderen!


Stap 1: De markup en styling

Laten we beginnen met een paar standaard markup en styling. Natuurlijk is dit niet het belangrijkste onderdeel van deze tutorial, ik zal je niet als een newbie behandelen.

De HTML

    HTML5 File API    

Upload uw afbeeldingen

Best simpel, toch? We hebben een formulier waarnaar berichten worden verzonden upload.php, waar we naar kijken in een tweede en een enkel invoerelement van type het dossier. Merk op dat het de boolean heeft meerdere kenmerk, waarmee de gebruiker meerdere bestanden tegelijk kan selecteren.

Dat is echt alles wat hier te zien is. Laten we verder gaan.

De CSS

lichaam font: 14px / 1.5 helvetica-neue, helvetica, arial, san-serif; padding: 10px;  h1 margin-top: 0;  #main width: 300px; margin: auto; achtergrond: #ececec; opvulling: 20px; border: 1px solid #ccc;  # afbeeldingslijst lijststijl: geen; margin: 0; padding: 0;  # afbeeldingslijst li achtergrond: #fff; border: 1px solid #ccc; text-align: center; padding: 20px; margin-bottom: 19px;  # image-lijst li img width: 258px; vertical-align: middle; rand: 1px vast # 474747; 

Absoluut geen shockers hier.


Stap 2: De PHP

We moeten de bestandsuploads ook aan de achterkant kunnen verwerken, dus laten we dat vervolgens bespreken.

upload.php

 $ error) if ($ error == UPLOAD_ERR_OK) $ name = $ _FILES ["images"] ["name"] [$ key]; move_uploaded_file ($ _FILES ["images"] ["tmp_name"] [$ key], "uploads /". $ _FILES ['images'] ['name'] [$ key]);  echo "

Succesvol geüploade afbeeldingen

";

Houd in gedachten dat dit de eerste regels waren van PHP waarin ik gemakkelijk een jaar had geschreven (ik ben een Ruby-man). Je zou waarschijnlijk wat meer moeten doen voor de veiligheid; We zorgen er echter gewoon voor dat er geen uploadfouten zijn. Als dat het geval is, gebruiken we de ingebouwde move_uploaded_file om het naar een te verplaatsen uploads map. Vergeet niet om ervoor te zorgen dat de map schrijfbaar is.

Dus nu zouden we een werkende upload-vorm moeten hebben. U kiest een afbeelding (meerdere, als u wilt en uw browser laat het u), klik op de ?Upload bestanden!? knop, en je krijgt het bericht ?Succesvol geüploade afbeeldingen.?

Dit is hoe ons mini-project er tot nu toe uitziet:

Maar kom op, het is 2011: we willen meer dan dat. U zult merken dat we jQuery en een gekoppeld hebben upload.js het dossier. Laten we dat nu openbreken.


Stap 3: JavaScript

Laten we geen tijd verspillen: hier gaan we!

(function () var input = document.getElementById ("images"), formdata = false; if (window.FormData) formdata = new FormData (); document.getElementById ("btn"). style.display = "none "; ();

Dit is waar we mee beginnen. We creëren twee variabelen: invoer is ons bestandinvoerelement; formdata wordt gebruikt om de afbeeldingen naar de server te verzenden als de browser dit ondersteunt. We initialiseren het voor vals en controleer vervolgens of de browser dit ondersteunt FormData; Als dit het geval is, maken we een nieuw FormData voorwerp. Als we de afbeeldingen kunnen indienen bij AJAX, hebben we de afbeeldingen niet nodig !? knop, zodat we het kunnen verbergen. Waarom hebben we het niet nodig? We gaan de foto's automatisch automatisch uploaden nadat de gebruiker ze heeft geselecteerd.

De rest van het JavaScript gaat naar je anonieme functie die zichzelf aanroept. Vervolgens maken we een kleine hulpfunctie die de afbeeldingen toont zodra de browser ze heeft:

functie showUploadedItem (bron) var list = document.getElementById ("afbeeldingslijst"), li = document.createElement ("li"), img = document.createElement ("img"); img.src = bron; li.appendChild (img); list.appendChild (li); 

De functie heeft één parameter nodig: de bron van het beeld (we zullen zien hoe we dat snel krijgen). Vervolgens vinden we de lijst gewoon in onze opmaak en maken we een lijstitem en afbeelding. We plaatsen de afbeeldingsbron in de bron die we hebben ontvangen, plaatsen de afbeelding in het lijstitem en plaatsen het lijstitem in de lijst. Voila!

Vervolgens moeten we de afbeeldingen daadwerkelijk maken, weergeven en uploaden. Zoals we al hebben gezegd, doen we dit wanneer het onchange gebeurtenis wordt afgevuurd op het invoerelement.

if (input.addEventListener) input.addEventListener ("change", function (evt) var i = 0, len = this.files.length, img, reader, file; document.getElementById ("response"). innerHTML = "Uploaden?" Voor (; < len; i++ )  file = this.files[i]; if (!!file.type.match(/image.*/))    , false); 

We hoeven ons geen zorgen te maken over IE's eigen evenementmodel, omdat IE9 + de standaard addEventListener-functie ondersteunt.

Er is meer, maar laten we hiermee beginnen. Ten eerste hoeven we ons geen zorgen te maken over het eigen eventmodel van IE, omdat IE9 + de standaard ondersteunt addEventListener functie (en IE9 en down ondersteunen onze nieuwe functies niet).

Wat willen we doen als de gebruiker bestanden heeft geselecteerd? Eerst maken we een paar variabelen. De enige belangrijke nu is len = this.files.length. De bestanden die de gebruiker heeft geselecteerd, zijn toegankelijk vanuit het object this.files. Op dit moment houden we ons alleen bezig met de lengte eigendom, zodat we de bestanden kunnen omlopen?

? dat is precies wat we hierna gaan doen. In onze loop zetten we het huidige bestand in het dossier voor gemakkelijke toegang. Het volgende dat we doen is bevestigen dat het bestand een afbeelding is. We kunnen dit doen door de type eigenschap met een reguliere expressie. We zijn op zoek naar een type dat begint met? Image? en wordt gevolgd door alles. (De dubbele knal aan de voorkant converteert het resultaat naar een booleaans schrift.)

Wat doen we als we een beeld in handen hebben??

if (window.FileReader) reader = new FileReader (); reader.onloadend = functie (e) showUploadedItem (e.target.result); ; reader.readAsDataURL (file);  if (formdata) formdata.append ("images []", bestand); 

We controleren om te zien of de browser het maken ondersteunt FileReader voorwerpen. Als dit het geval is, maken we er een aan.

Dit is hoe we een gebruiken FileReader object: we gaan onze het dossier bezwaar tegen de reader.readAsDataURL methode. Hiermee wordt een gegevens-URL gemaakt voor de geüploade afbeelding. Het werkt echter niet zoals je zou verwachten. De gegevens-URL wordt niet door de functie doorgegeven. In plaats daarvan zal de gegevens-URL deel uitmaken van een gebeurtenisobject.

Met dat in gedachten, moeten we een functie registreren op de reader.onloadend evenement. Deze functie neemt een gebeurtenisobject, waarmee we de gegevens-URL ophalen: die is op e.target.result (Ja, e.target is de lezer object, maar ik had problemen bij het gebruik lezer in plaats van e.target binnen deze functie). We geven deze gegevens-URL gewoon door aan onze showUploadedItem functie (die we hierboven schreven).

Vervolgens kijken we naar de formdata voorwerp. Denk eraan, als de browser dit ondersteunt FormData, formdata zal een ... zijn FormData voorwerp; anders zal het zijn vals. Dus, als we een hebben FormData object, we gaan de toevoegen methode. Het doel van a FormData object is om waarden die je indient te bewaren via een formulier; dus de toevoegen methode neemt eenvoudigweg een sleutel en een waarde. In ons geval is onze sleutel afbeeldingen[]; door de vierkante haakjes aan het einde toe te voegen, zorgen we ervoor dat we elke keer opnieuw toevoegen een andere waarde, we voegen het feitelijk aan die array toe, in plaats van het te overschrijven beeld eigendom.

We zijn bijna klaar. In onze for-lus hebben we alle afbeeldingen voor de gebruiker weergegeven en deze aan de gebruiker toegevoegd formdata voorwerp. Nu moeten we de afbeeldingen uploaden. Buiten de voor loop, hier is het laatste stukje van onze puzzel:

if (formdata) $ .ajax (url: "upload.php", typ: "POST", data: formdata, processData: false, contentType: false, success: function (res) document.getElementById ("response" ) .innerHTML = res;); 

Nogmaals, we moeten ervoor zorgen dat we dat hebben FormData ondersteuning; als we dat niet doen, de? Upload Files !? knop zal zichtbaar zijn, en dat is hoe de gebruiker de foto's zal uploaden. Echter, als we dat hebben FormData ondersteuning, we zorgen voor uploaden via AJAX. We gebruiken jQuery om alle eigenaardigheden van AJAX via browsers te verwerken.

Je bent waarschijnlijk bekend met jQuery's $ .ajax methode: u geeft het een optie-object door. De url, type, en succes eigenschappen moeten duidelijk zijn. De gegevens eigendom is ons formdata voorwerp. Let op die data verwerken en contentType eigenschappen. Volgens de documentatie van jQuery, data verwerken is waar standaard, en verwerkt en transformeert de gegevens in een querystring. We willen dat niet doen, dus we hebben dit ingesteld vals. We zijn ook aan het poseren contentType naar vals om ervoor te zorgen dat de gegevens naar de server gaan zoals we verwachten.

En dat is het. Wanneer de gebruiker de pagina laadt, zien ze dit:

En nadat ze de afbeeldingen hebben geselecteerd, zien ze dit:

En de afbeeldingen zijn geüpload:


Het zit er op!

Het uploaden van bestanden via AJAX is best gaaf en het is geweldig dat deze nieuwe technologieën dat ondersteunen zonder de noodzaak van lange hacks. Als je vragen hebt over wat we hier hebben gedaan, klik dan op deze opmerkingen! Heel erg bedankt voor het lezen!

En als u nog steeds hulp nodig hebt bij dit of een ander coderingsprobleem, zoek dan ondersteuning bij Envato Studio.

Leer JavaScript: de complete gids

We hebben een complete handleiding samengesteld waarmee u JavaScript kunt aflezen, of u net bent begonnen als webontwikkelaar of dat u meer geavanceerde onderwerpen wilt verkennen.