
🚀 Mitme faili üleslaadimine HTML-i ja PHP abil
Kasutaja peab üles laadima viis pilti, aga vorm võtab vastu ainult ühe. Või klient soovib paketina dokumentide üleslaadimist, kus igale failile on lisatud pealkiri. See pole ulme: see on tavaline ülesanne, mille PHP lahendab kolmekümne reaga.
Probleem on selles, et enamik õpetusi näitab ühe faili üleslaadimist. Mitme faili üleslaadimine töötab teisiti: ühe faili asemel on failide massiiv, seostamine lisaväljadega, kaitse ülekirjutamise eest. Allpool on töötav teostus nullist kuni kasutusvalmis jupini.
💡 Kiire ülevaade:
- Loo HTML-vorm atribuudiga
enctype="multipart/form-data"jafile-väljaga, millel onmultipleatribuut. - Töötle PHP-s
$_FILESmassiivi: käi läbi indeksid ja kasuta iga faili puhulmove_uploaded_file(). - Lisa enne kettale salvestamist laiendi- ja suurusevalideerimine.
- „Fail + pealkiri" sidumiseks kasuta paralleelmassiive
title[]jafileUpload[].
Kiire videoülevaade samast teemast, HTML-vormist kuni failide andmebaasi salvestamiseni:
Samm 1: HTML-vorm mitme faili üleslaadimiseks
Esmalt ehita vorm. Võtmepunktid: atribuut enctype väärtusega multipart/form-data ja sisestusväli atribuudiga multiple. Ilma enctype'ta server lihtsalt ei võta faile vastu; see pole PHP viga, vaid HTTP-spetsifikatsiooni oma.
Nimeta väli massiivina: fileUpload[]. Nurksulud lõpus ütlevad PHP-le, et server saab nimekirja, mitte ühe faili.
1 <form action="" method="post" enctype="multipart/form-data"> 2 <label>Select files:</label> 3 <input type="file" name="fileUpload[]" multiple> 4 <input type="submit" name="Submit" value="Upload"> 5 </form>
Ülaltoodud vorm võimaldab failidialoogis korraga valida suvalise arvu faile. Brauser pakib need mitmeosaliseks päringuks ja saadab serverisse. Selles etapis pole JavaScripti vaja.
Samm 2: Failimassiivi PHP töötlus
Kui vorm serverisse saadetakse, täidab PHP superglobaalse $_FILES massiivi. Kuid struktuur erineb ühe faili üleslaadimisest: võtmed name / tmp_name / size / error muutuvad massiivideks, kus indeks vastab faili järjekorranumbrile.
Käime indeksid läbi ja salvestame iga faili, kasutades move_uploaded_file():
1 <?php 2 3 $target_dir = 'uploads/'; 4 5 if (isset($_FILES['fileUpload']['name'])) { 6 7 $total_files = count($_FILES['fileUpload']['name']); 8 9 for ($key = 0; $key < $total_files; $key++) { 10 11 // Skip empty fields (no file selected) 12 if (isset($_FILES['fileUpload']['name'][$key]) 13 && $_FILES['fileUpload']['size'][$key] > 0) { 14 15 $original_filename = $_FILES['fileUpload']['name'][$key]; 16 $target = $target_dir . basename($original_filename); 17 $tmp = $_FILES['fileUpload']['tmp_name'][$key]; 18 19 move_uploaded_file($tmp, $target); 20 } 21 } 22 }
Lisa see kood oma alamteema functions.php faili või Code Snippets pluginasse ja 1. sammu vorm hakkab faile vastu võtma.
Pane tähele, et basename() eemaldab failinimest tee. See kaitseb tee läbimise rünnete eest: ründaja võib nimeks saata ../../wp-config.php. basename() jätab alles ainult wp-config.php, kuid järgmine kaitsetase peaks ikkagi olema laiendivalideerimine.
Samm 3: Failitüübi ja suuruse kontrollimine
Kõike, mida brauser saadab, ei saa võtta vastu „nagu on". Minimaalne kaitse: lubatud laiendite nimekiri ja suuruspiirang.
Laiendikontroll, kasutades pathinfo() koos PATHINFO_EXTENSION lipuga. Teisenda väiketähtedeks ja võrdle lubatud laienditega:
1 $allowed_ext = array('jpg', 'jpeg', 'png', 'gif', 'bmp', 'pdf', 'doc', 'docx'); 2 $ext = strtolower(pathinfo($_FILES['fileUpload']['name'][$key], PATHINFO_EXTENSION)); 3 4 if (!in_array($ext, $allowed_ext)) { 5 $errors[$key] = 'Invalid file type: ' . $ext; 6 continue; 7 }
Suuruse kontrollimine on veelgi lihtsam; size väärtus baitides on juba $_FILES sees:
1 $max_file_size = 5 * 1024 * 1024; // 5 MB 2 3 if ($_FILES['fileUpload']['size'][$key] > $max_file_size) { 4 $errors[$key] = 'File exceeds the allowed size (5 MB)'; 5 continue; 6 }
Paiguta mõlemad kontrollid enne move_uploaded_file() samasse tsüklisse. Valideerimise läbi kukkunud failid kettale ei jõua. Kogu vead massiivi ja pärast töötlust kuva kasutajale nimekiri, mis näitab, milline fail ja miks läbi kukkus. Ilma selleta näeb kasutaja lihtsalt tühja tulemust ja lahkub, eeldades, et vorm on katki. Iga tagasilükatud faili kohta teata nimi ja põhjus, näiteks „photo.png: vale tüüp" või „archive.zip: suurus ületatud".
Samm 4: Failide ümbernimetamine üleslaadimisel
Kui kaks kasutajat laadivad üles photo.jpg, kirjutab teine fail esimese üle. Lahendus on salvestamisel unikaalse nime genereerimine. Lihtsaim lähenemine: asenda tühikud alakriipsudega ja lisa time().
1 if (isset($_FILES['fileUpload']['name'][$key]) 2 && $_FILES['fileUpload']['size'][$key] > 0) { 3 4 $original_filename = $_FILES['fileUpload']['name'][$key]; 5 6 // Extension separately 7 $ext = pathinfo($original_filename, PATHINFO_EXTENSION); 8 9 // Name without extension 10 $filename_without_ext = basename($original_filename, '.' . $ext); 11 12 // New name: no spaces + timestamp 13 $new_filename = str_replace(' ', '_', $filename_without_ext) 14 . '_' . time() . '.' . $ext; 15 16 move_uploaded_file( 17 $_FILES['fileUpload']['tmp_name'][$key], 18 $target_dir . $new_filename 19 ); 20 }
time() tempel tagab unikaalsuse sekundi täpsusega. Suure liiklusega projektides asenda see uniqid() või UUID-ga: kaks samaaegset päringut sama sekundi jooksul on piisavad, et põhjustada kokkupõrge ja kaotada üks failidest. Samuti paljastab time() failinimes üleslaadimise kuupäeva, mis on mõnikord ebasoovitav. UUID ramsey/uuid kaudu kõrvaldab mõlemad probleemid täielikult.
Samm 5: Üleslaadimine koos lisaväljadega igale failile
Mõnikord on vaja igale failile lisada pealkiri, kirjeldus või kategooria. Ühe „pealkiri + fail" paari asemel lood mitu, nimetades väljad massiividena:
1 <form action="" method="post" enctype="multipart/form-data"> 2 3 <input type="text" name="title[]" placeholder="Title"> 4 <input type="file" name="fileUpload[]"> 5 6 <input type="text" name="title[]" placeholder="Title"> 7 <input type="file" name="fileUpload[]"> 8 9 <input type="text" name="title[]" placeholder="Title"> 10 <input type="file" name="fileUpload[]"> 11 12 <input type="submit" name="Submit" value="Upload"> 13 14 </form>

Serveri poolel on $_POST['title'] ja $_FILES['fileUpload']['name'] paralleelmassiivid. Indeks 0 ühes vastab indeksile 0 teises. Töötlus kasutab sama tsüklit, kuid nüüd koos pealkirja sidumisega:
1 $total_files = count($_FILES['fileUpload']['name']); 2 3 for ($key = 0; $key < $total_files; $key++) { 4 5 if ($_FILES['fileUpload']['size'][$key] === 0) { 6 continue; // empty field — skip 7 } 8 9 $title = isset($_POST['title'][$key]) ? $_POST['title'][$key] : ''; 10 $tmp = $_FILES['fileUpload']['tmp_name'][$key]; 11 $fname = basename($_FILES['fileUpload']['name'][$key]); 12 $target = $target_dir . time() . '_' . $fname; 13 14 if (move_uploaded_file($tmp, $target)) { 15 // Save $title and $target to the database 16 // or into an array for further processing 17 } 18 }
Veendu, et title[] väljade arv vastab fileUpload[] väljade arvule vormis. Kui kasutaja lisab välju dünaamiliselt JavaScripti abil, peavad kõik indeksid olema järjestikused ilma lünkadeta. PHP ei tihenda automaatselt hõredaid massiive, seega $_POST['title'][5] võib eksisteerida, samas kui $_FILES['fileUpload']['name'][5] mitte.
Praktikas katab see lähenemine hea poole klientide ülesannetest: pildigaleriid pealkirjadega, dokumentide üleslaadimine siltidega, CV-de esitamine portfooliodega. Sama paralleelmassiivide põhimõte töötab kirjelduse, kategooria, järjekorra ja mis tahes muude väljade puhul.
⁉️🤔 Korduma kippuvad küsimused
Miks faili ei ilmu $_FILES massiivi, kuigi vorm saadeti?
Üheksal juhul kümnest puudub
<form>sildiltenctype="multipart/form-data". Ilma selleta saadab brauser andmed tavalise tekstina ja PHP ei täida$_FILESmassiivi. Kontrolli kapost_max_sizejaupload_max_filesizeväärtusi failisphp.ini; kummagi ületamine annab tulemuseks tühja massiivi ilma nähtavate vigadeta.
Kuidas piirata ühe päringu kogu üleslaadimismahtu?
post_max_sizedirektiiv failisphp.inikärbib kogu POST-päringu keha, sealhulgas failid ja tekstiväljad. Vaikeväärtus on vastavalt PHP dokumentatsioonile 8 MB. Määra see suuremaks kuiupload_max_filesize, lisades varu mitmeosalise kodeeringu jaoks (umbes 20%). Hulgilaadimiste puhul suurenda mõlemat parameetrit:upload_max_filesize = 20Mjapost_max_size = 25M.
Kas faile saab JavaScripti abil asünkroonselt üles laadida?
Jah. Kasuta
FormDatajafetchkoosmethod: 'POST'. LisafileUpload[]väljad, kasutades iga valitud faili puhulformData.append('fileUpload[]', file). Ära määraContent-Typepäist käsitsi; brauser seab automaatseltmultipart/form-datakoos õige eraldajaga. Visuaalse tagasiside jaoks kasuta edenemisribaXMLHttpRequest.upload.onprogresskaudu, kunafetchei võimalda edenemist otse jälgida.
Aga turvalisus: ründaja laadib pildi asemel üles PHP-skripti?
Laiendikontroll 3. sammust on esimene kaitseliin. Teine: salvesta üleslaaditud failid VÄLJAPOOLE saidi juurkausta või kataloogi, kus
.htaccesskeelab käivitamise (php_flag engine off). Kolmas: nimeta failid salvestamisel ümber (4. samm); isegi kuishell.phpläbib laiendifiltri, muutub seeshell_1718300000.php-ks, mis pole käivitusõigusteta ohtlik. Neljas: kontrolli MIME-tüüpi mitte$_FILES['type']kaudu (saadab brauser, kergesti võltsitav), vaidfinfo(PHP sisseehitatud Fileinfo) abil, mis loeb faili signatuuri.
Mida see lähenemine annab: tervikpilt
Oled ehitanud üleslaadimissüsteemi, mis käsitleb karbist välja kolme stsenaariumi: paketina failid ühe nupuga, üksiku faili üleslaadimine koos valideerimisega ja „fail + metaandmed" sidumine paralleelmassiivide kaudu. Kood on iga sammu kohta umbes kolmkümmend rida, ei midagi üleliigset.
Kui töötad WordPressis, paiguta töötleja oma alamteema functions.php faili või Code Snippets pluginasse. Tavalise PHP puhul pane töötlusskript lihtsalt vormi tegevuse sihtkohta.
Selle artikli kood katab enamiku tüüpilisi üleslaadimisülesandeid. Ülejäänud stsenaariume (tükeldatud üleslaadimine suurte failide jaoks, otse üleslaadimine S3-ühilduvasse salvestusruumi ja lohista-ja-lohista koos eelvaatega) käsitletakse eraldi artiklites. Kirjuta kommentaaridesse, milline neist on sinu projekti jaoks asjakohane, ja me seame selle prioriteediks.



