Överför filer med AJAX

Jag verkar inte kunna nå slutet på de roliga saker du kan göra med framväxande webbteknik. Idag ska jag visa dig hur man gör någonting som - till sista gången - har varit nästan oöverträffad: ladda upp filer via AJAX.

Åh, det har säkert varit hackar; men om du är som jag, och känner dig smutsig varje gång du skriver iframe, du kommer att gilla så mycket. Gå med mig efter hoppet!

Letar efter en snabb lösning?

Om du letar efter en snabb lösning finns det en bra samling av filuppladdningsskript och program över på Envato Market.я

Den här HTML5-filuppladaren är speciellt smidig - du kan enkelt lägga till filer genom att dra och släppa dem eller klicka. Alla filer laddas upp via AJAX eller kan läggas till i ett formulär, och filer kan bytas om innan de laddas upp. En bra, snabb lösning om det är vad du letar efter!


Varför får vi inte de dåliga nyheterna med?

Det här fungerar inte i varje webbläsare. Men med viss progressiv förbättring (eller vad som helst det nuvarande buzzwordet) har vi en uppladdningssida som fungerar direkt tillbaka till IE6 (om än utan AJAXy-bitarna).

Vår AJAX-uppladdning kommer att fungera så länge som FormData är tillgänglig; annars kommer användaren att få en vanlig uppladdning.

Det finns tre huvudkomponenter till vårt projekt.

  • De flera olika attribut på filen inmatning element.
  • De Filereader objekt från det nya fil API.
  • De FormData objekt från XMLHttpRequest2.

Vi använder flera olika attribut för att tillåta användaren att välja flera filer för uppladdning (flera filuppladdningar fungerar normalt även om FormData är inte tillgänglig). Som du ser, Filereader tillåter oss att visa användarminiatyrerna av filerna de laddar upp (vi förväntar oss bilder).

Ingen av våra tre funktioner fungerar i IE9, så alla IE-användare får en vanlig uppladdningsupplevelse (även om jag förstår stöd för "FileReader" finns i IE10 Dev Preview 2). Filereader fungerar inte i den senaste versionen av Safari (5.1), så de kommer inte att få miniatyrerna, men de får AJAX-uppladdningen och bekräftelsemeddelandet. Slutligen har Opera 10,50 Filereader stöd men inte FormData stöd, så de kommer att få miniatyrer, men vanliga uppladdningar.

Med det ur vägen, låt oss få kodning!


Steg 1: Markup och Styling

Låt oss börja med några grundläggande markup och styling. Självklart är detta inte huvuddelen av denna handledning, jag kommer inte att behandla dig som en nybörjare.

HTML

    HTML5-fil API    

Ladda upp dina bilder

Ganska grundläggande, va? Vi har en blankett som postar till upload.php, som vi ska titta på på en sekund, och ett enda ingångselement av typen fil. Lägg märke till att den har booleska flera olika attribut som tillåter användaren att välja flera filer samtidigt.

Det är verkligen allt som finns att se här. Låt oss gå vidare.

CSS

kropp font: 14px / 1.5 helvetica-neue, helvetica, arial, san-serif; padding: 10px;  h1 margin-top: 0;  #main width: 300px; marginal: auto; bakgrund: #ececec; vaddering: 20px; gränsen: 1px solid #ccc;  # bildlista listestil: none; marginal: 0; padding: 0;  # bildlista li bakgrund: #fff; gränsen: 1px solid #ccc; text-align: center; padding: 20px; margin-bottom: 19px;  # bildlista li img width: 258px; vertikaljustering: mitt; gräns: 1px fast # 474747; 

Absolut ingen chocker här.


Steg 2: PHP

Vi måste kunna hantera filuppladdningar på baksidan också, så låt oss täcka nästa.

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]);  eko "

Uppladdade bilder med framgång

";

Tänk på att dessa var de första raderna i PHP som jag hade skrivit in på ett enkelt år (jag är en Ruby-kille). Du borde noga göra lite mer för säkerhet; Vi gör dock helt enkelt till att det inte finns några uppladdningsfel. Om så är fallet använder vi den inbyggda move_uploaded_file att flytta den till en uppladdningar mapp. Glöm inte att se till att mappen är skrivbar.

Så, just nu borde vi ha ett fungerande uppladdningsformulär. Du väljer en bild (flera, om du vill och din webbläsare låter dig) klickar du på ?Ladda upp filer!? knappen och du får meddelandet ?Uppladdade bilder med framgång.?

Så här ser vårt mini-projekt ut så här långt:

Men kom igen, det är 2011: vi vill ha mer än det. Du märker att vi har länkat upp jQuery och en upload.js fil. Låt oss knäcka det som öppnas nu.


Steg 3: JavaScript

Låt oss inte slösa tid: här går vi!

(funktion () var input = document.getElementById ("bilder"), formdata = false; om (window.FormData) formdata = ny FormData (); document.getElementById ("btn"). style.display = "none "; ();

Här är vad vi börjar med. Vi skapar två variabler: inmatning är vårt filinmatningselement; formdata kommer att användas för att skicka bilderna till servern om webbläsaren stöder det. Vi initierar det till falsk och kontrollera sedan om webbläsaren stöder FormData; Om det gör skapar vi en ny FormData objekt. Om vi ​​också kan skicka in bilderna med AJAX behöver vi inte? Ladda upp bilder !? knappen, så vi kan gömma det. Varför behöver vi inte det? Nå ska vi automatiskt ladda upp bilderna omedelbart efter att användaren valt dem.

Resten av JavaScript kommer att gå in i din anonyma egenfunktion. Vi skapar sedan en liten hjälparfunktion som visar bilderna när webbläsaren har dem:

funktion showUploadedItem (source) var list = document.getElementById ("bildlista"), li = document.createElement ("li"), img = document.createElement ("img"); img.src = source; li.appendChild (img); list.appendChild (li); 

Funktionen tar en parameter: bildkällan (vi får se hur vi får det snart). Då hittar vi bara listan i vår markering och skapar en lista och bild. Vi sätter bildkällan till källan vi mottog, lägger bilden i listobjektet och lägger listan i listan. voila!

Därefter måste vi faktiskt ta bilderna, visa dem och ladda upp dem. Som vi har sagt gör vi det här när onChange händelse avfyras på ingångselementet.

om (input.addEventListener) input.addEventListener ("ändra", funktion (evt) var i = 0, len = this.files.length, img, läsare, fil; document.getElementById ("response"). innerHTML = "Uploading" för (; i < len; i++ )  file = this.files[i]; if (!!file.type.match(/image.*/))    , false); 

Vi behöver inte oroa oss för IEs proprietära händelsesmodell, eftersom IE9 + stöder standard addEventListener-funktionen.

Det finns mer, men låt oss börja med detta. För det första behöver vi inte oroa oss för IEs proprietära händelsemodell, eftersom IE9 + stöder standarden addeventlistener funktion (och IE9 och ner stöder inte våra nya funktioner).

Så vad vill vi göra när användaren har valt filer? Först skapar vi några variabler. Den enda viktigaste just nu är len = this.files.length. Filerna som användaren har valt kommer att vara tillgänglig från objektet this.files. Just nu är vi bara intresserade av längd egendom, så vi kan slingra över filerna?

? vilket är exakt vad vi gör nästa. Inom vår slinga ställer vi den aktuella filen till fil för enkel åtkomst. Nästa sak som vi gör är att bekräfta att filen är en bild. Det kan vi göra genom att jämföra typ egendom med ett reguljärt uttryck. Vi letar efter en typ som börjar med? Bild? och följs av någonting. (Dubbla bang framför konverterar resultatet till en booleska.)

Så vad gör vi om vi har en bild på våra händer?

om (window.FileReader) läsare = ny FileReader (); reader.onloadend = function (e) showUploadedItem (e.target.result); ; reader.readAsDataURL (fil);  om (formdata) formdata.append ("images []", fil); 

Vi kontrollerar om webbläsaren stöder att skapa Filereader objekt. Om det gör skapar vi en.

Så här använder vi en Filereader objekt: Vi ska passera vårt fil protestera mot reader.readAsDataURL metod. Detta skapar en datalogg för den uppladdade bilden. Det fungerar inte som du kanske förväntar dig. Data url går inte tillbaka från funktionen. Istället kommer data url att vara en del av ett händelseobjekt.

Med det i åtanke måste vi registrera en funktion på reader.onloadend händelse. Den här funktionen tar ett händelseobjekt, genom vilket vi får dataadressen: den är på e.target.result (ja, e.target är läsare objekt, men jag hade problem vid användning läsare istället för e.target inuti denna funktion). Vi kommer bara att skicka den här datalösenordet till vår showUploadedItem funktion (som vi skrev ovan).

Därefter söker vi efter formdata objekt. Kom ihåg, om webbläsaren stöder FormData, formdata kommer att vara en FormData objekt; annars kommer det att bli falsk. Så, om vi har en FormData objekt, vi kommer att ringa bifoga metod. Syftet med a FormData objektet är att hålla värden som du skickar via ett formulär så, den bifoga Metoden tar helt enkelt en nyckel och ett värde. I vårt fall är vår nyckel bilder[]; genom att lägga till fyrkantiga parenteser till slutet, ser vi till varje gång vi bifoga ett annat värde, vi lägger faktiskt det till den matrisen istället för att skriva över bild fast egendom.

Vi är nästan färdiga. I vår för loop har vi visat var och en av bilderna för användaren och lagt till dem i formdata objekt. Nu behöver vi bara ladda upp bilderna. Utanför för loop, här är den sista delen av vårt pussel:

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

Återigen måste vi se till att vi har FormData Stöd; om vi inte gör det, ladda upp filer !? knappen kommer att vara synlig, och det är hur användaren ska ladda upp bilderna. Men om vi har FormData support, vi tar hand om uppladdning via AJAX. Vi använder jQuery för att hantera alla oddities av AJAX över webbläsare.

Du är förmodligen bekant med jQuery's $ .ajax Metod: Du skickar det till ett alternativobjekt. De url, typ, och Framgång Egenskaper ska vara uppenbara. De data egendom är vårt formdata objekt. Lägg märke till dem processData och innehållstyp egenskaper. Enligt jQuerys dokumentation, processData är Sann som standard, och kommer att bearbeta och omvandla data till en frågesträng. Vi vill inte göra det, så vi bestämmer det här falsk. Vi ställer också in innehållstyp till falsk för att säkerställa att data kommer till servern som vi förväntar oss att den ska.

Och det är allt. Nu när användaren laddar sidan ser de detta:

Och efter att ha valt bilderna ser de detta:

Och bilderna har laddats upp:


Vi är klara!

Ladda upp filer via AJAX är ganska coolt, och det är fantastiskt att dessa nya tekniker stöder det utan att behöva ha långa hackar. Om du har några frågor om vad vi har gjort här, slå dessa kommentarer! Tack så mycket för att läsa!

Och om du fortfarande behöver hjälp med det här eller någon annan kodningsproblem, hitta support på Envato Studio.

Lär dig JavaScript: Den fullständiga guiden

Vi har byggt en komplett guide för att hjälpa youяlearn JavaScript, oavsett om du precis börjat som webbutvecklare eller vill utforska mer avancerade ämnen.