Failu augšupielāde ar progresa indikatoru
Deniss Fedotovs (deni2s), 19.10.2008., 17:39Augšupielādējot failu caur HTML formu uz servera sākot ar PHP 5.2 versiju sākot ir iespējams sekot līdzi, cik daudz no faila jau ir ielādējies. Šajā rakstā aprakstīts, kā šo iespēju izmantot praktiski.
Nepieciešamās priekšzināšanas - HTML, mazliet no PHP un AJAX.
Servera sagatavošana
Sāksim ar to, ka uz servera ar PHP 5.2 ir jābūt pieinstalētam APC jeb Alternative PHP Cache.Tālāk ir jāpārliecinās, ka ir saliktas pareizas PHP direktīvas php.ini failā (tās var aplūkot ar PHP funkciju
phpinfo();
):apc.enabled=on
apc.rfc1867=on
apc.rfc1867_name=APC_UPLOAD_PROGRESS
Jāpārliecinās, kāds ir norādīts maksimālais faila izmērs, kuru var nosūtīt uz serveri ar
POST
pieprasījumu (šajā gadījumā - 20Mb).file_uploads=on
post_max_size=20M
upload_max_size=20M
Gadījumā, ja skripts nedarbojas dēļ tā, ka fails augšupielādējas pārāk ilgi, ir vērts apskatīt arī direktīvas
max_input_time
vērtību.
Faila nosūtīšanas formas sagatavošana
Tālāk izveidojam PHP failu upload.php ar faila augšupielādes formu:<?php
//nodefinējam unikālu identifikatoru
$id = uniqid('');
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="lv" lang="lv">
<head>
<title>Faila augšupielādes forma</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script src="progress.js" type="text/javascript"></script>
</head>
<body>
<h1>Faila augšupielāde</h1>
<form action="post.php" method="post" enctype="multipart/form-data">
<div>
<input type="hidden" name="APC_UPLOAD_PROGRESS"
value="<?php echo($id) ?>"/>
<input type="hidden" name="MAX_FILE_SIZE" value="20971520"/>
<label for="file">Fails (max izmērs 200 MB): </label>
<input type="file" id="file" name="file"/>
<br />
<label for="apraksts">Apraksts: </label>
<input type="text" id="apraksts" name="apraksts"/>
<br />
<input type="submit" value="Nosūtīt"
onclick="apc_progress('<?php echo($id) ?>');return true;"/>
<div id="apc_progress"> </div>
</div>
</form>
</body>
</html>
Uzreiz izstāstīšu, ko kas nozīmē šajā kodā.
HTML taga
<form>
atribūts enctype="multipart/form-data"
norāda uz to, ka ar šīs formas palīdzību tiks sūtīts arī fails.<input type="hidden" name="MAX_FILE_SIZE" value="20971520"/>Ar šo rindiņu tiek norādīts, ka maksimālais sūtāmais faila izmērs ir 20971520 baiti (jeb 20 Mb). Patiesībā, pārlūkam pirms sūtīšanas būtu jāpārbauda, vai fails ir lielāks vai mazāks par norādīto izmēru, taču cik meklēju informāciju, tad vismaz Firefox 2.0 un Internet Explorer 6.0 šo iespēju neatbalsta.
<input type="hidden" name="APC_UPLOAD_PROGRESS" value="<?php echo($id) ?>"/>Šī rindiņa ir tā, kas atbild par faila augšupielādes progresa indikāciju. Atribūta
name
vērtībai jābūt tādai pašai, kā ir norādīts iekš php.ini apc.rfc1867_name
vērtība. Savukārt atribūta value
vērtība ir iepriekš ar PHP palīdzību izveidots unikāls identifikators, kas tiks izmantots, lai piekļūtu informācijai par augšupielādējamo failu.Ļoti būtiski ir atcerēties, ka abām iepriekš aprakstītajām rindiņām jābūt pirms rindiņas šīs rindiņas, kura atbild par to, lai tiktu augšupielādēts fails:
<input type="file" id="file" name="file"/>
Tā kā ar POST pieprasījumu informācija tiek nosūtīta tādā secībā, kādā tā tiek norādīta, tad pretējā gadījumā serveris saņems unikālo faila augšupielādes identifikatoru tikai pēc tam, kad tiks augšupielādēts fails par visiem 100%. Citiem vārdiem sakot, tad, kad tas vairs nebūs vajadzīgs.
<input type="submit" value="Nosūtīt"Te mēs norādam, ka noklikšķinot uz nosūtīšanas pogu, jāpalaiž javascript funkcija
onclick="apc_progress('<?php echo($id) ?>');return true;"/>
apc_progress()
kurai par parametru iedodam iepriekš izveidoto faila unikālo identifikatoru. Tieši šī funkcija būs atbildīga par faila augšupielādes informācijas saņemšanu ar AJAX palīdzību.Un visbeidzot rindiņa, kuras vietā būs redzams faila augšupielādes progresa indikators:
<div id="apc_progress"></div>
Informācijas par augšupielādējamo failu iegūšana
Izveidojam PHP failu progress.php, kurš nodrošinās AJAX ar nepieciešamo informāciju par to, cik tālu fails ar piešķirto identifikatoru ir augšupielādēts.<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s").'GMT');
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');
header('Content-Type: text/html; charset=utf-8');
if(isset($_GET['id']))
{
$status=apc_fetch(('upload_'.$_GET['id']));
echo('Augšupielādēti '.$status['current'].' baiti no '.$status['total'].' baitiem.');
}
?>
Kā redzams, PHP funkcija
apc_fetch()
ir tā, kas atgriež informāciju masīvā par augšupielādējamo failu, kamēr tas vēl tiek augšupielādēts. Par funkcijas apc_fetch()
parametru tiek iedots iepriekš izveidotais faila unikālais identifikators, kuram priekšā ir pielikts prefikss upload_
.Funkcija atgriež masīvu, kura elements
['current']
ir faila pašreizējais augšupielādētais izmērs baitos, bet elements ['total']
- faila kopējais izmērs baitos.
Visa apvienošana kopā ar AJAX palīdzību
Tagad atliek to visu apvienot kopā ar AJAX palīdzību. Izveidojam failu progress.js ar šādu saturu://f-ja, kas palaižas nospiežot nosūtīšanas pogu
function apc_progress(nr)
{
//paņemam div elementu, kurā rādīsim progresu
var progdiv=document.getElementById('apc_progress');
//padzēšam div saturu -
//nepieciešams, ja lietotājs nospiež BACK pogu pārlūkā
progdiv.removeChild(progdiv.firstChild);
//parādam tekstu, ka notiek datu ielāde
var txt=document.createTextNode('Lūdzu uzgaidi...');
progdiv.appendChild(txt);
//pēc sekundes palaižam AJAX f-ju, kas saņems datus
setTimeout(('apc("'+nr+'");'),1000)
}
//f-ja, kas parāda saņemto augšupielādes progresu
function update_apc_status(txt2,nr)
{
//paņemam div elementu, kurā rādam progresu
var progdiv=document.getElementById('apc_progress');
//padzēšam div saturu -
progdiv.removeChild(progdiv.firstChild);
//parādam saņemto info par faila ielādes progresu
var txt=document.createTextNode(txt2);
progdiv.appendChild(txt);
//pēc 1/10 sekundes palaižam atkal AJAX f-ju,
//lai atjaunotu informāciju par failu augšupielādi
setTimeout(('apc("'+nr+'");'),100)
}
//AJAX f-ja, kas saņem informāciju no faila apc_progress.php
//par faila augšupielādes progresu
function apc(nr)
{
if (prog.readyState==4 || prog.readyState==0)
{
//nododam failam progress.php kā parametru faila unikālo identifikatoru
prog.open('GET','progress.php?id='+nr+'&rand='+Math.floor(Math.random()*1000),true);
prog.onreadystatechange=function()
{
if(prog.readyState==4)update_apc_status(prog.responseText,nr);
};
prog.send(null)
}
}
// Šī ir galvenā AJAX f-ja, kas ir diezgan sarežģīta, tāpēc
// vienkārši neaiztieciet to, bet atstājiet, kā ir.
function getHTTPObject(){
var xmlhttp;
/*@cc_on
@if (@_jscript_version >=5)
try{xmlhttp=new ActiveXObject("Msxml2.XMLHTTP")}
catch(e){
try{xmlhttp=new ActiveXObject("Microsoft.XMLHTTP")}
catch(E){xmlhttp=false}}
@else
xmlhttp=false;
@end @*/
if(!xmlhttp && typeof XMLHttpRequest!='undefined')
try{xmlhttp=new XMLHttpRequest()}
catch(e){xmlhttp=false}
return xmlhttp}
// sasaistam mainīgo prog ar austāk esošo AJAX f-ju
var prog=getHTTPObject();
Kods ir diezgan labi komentēts, tāpēc to šeit sīkāk neiztirzāšu. Ja ir kādas neskaidrības par to, kā darbojas AJAX, tad es ieteiktu izlasīt rakstu "AJAX - praktisks piemērs", kur ir diezgan sīki izskaidrots kas un kā.
Nobeigumā
Jāņem vērā, ka PHP funkcijaapc_fetch()
parāda nevis paša augšupielādējamā faila izmēru, bet gan visa POST
pieprasījuma izmēru, līdz ar to, ja tiks vienā formā augšupielādēti vairāki faili, tad apc_fetch()
funkcija rādīs informāciju par visiem failiem kopā (un papildus parametriem, kas tiek nodoti ar POST
pieprasījumu). Tāpēc nebrīnieties, ka pat nosūtot formu kurā vispār nav norādīts augšupielādējamais fails, tiek uzrādīt daži baiti, kas tiek nosūtīti.Rakstā apskatītais piemērs ir tīri izglītības mērķiem, praktiskā situācijā, protams, augšupielādējamais fails vēl ir pēc nepieciešamības jāapstrādā uz servera, kā arī progresa indikatoru var "izskaistināt" ar CSS un uzlabot.
Pārbaudīt darbībā Failu augšupielādes progresa indikātoru var te, bet lejupielādēt ZIP failā te: file-upload-progress-bar.zip.
Raksta sagatavošanā izmantotie resursi:
Par web.hc.lv
web.hc.lv ir vortāls, kurā tiek aplūkoti mājaslapu veidošanas un mārketinga aspekti, no idejas līdz gandarījumam.
Reklāma