Failu augšupielāde ar progresa indikatoru

Deniss Fedotovs (deni2s), 19.10.2008., 17:39

Augš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.

Failu augšupielādes progresa indikators

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">&nbsp;</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" 
onclick="apc_progress('<?php echo($id) ?>');return true;"/>
Te mēs norādam, ka noklikšķinot uz nosūtīšanas pogu, jāpalaiž javascript funkcija 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 funkcija apc_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.

Failu augšupielādes progresa indikatorsRakstā 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:

5 komentāri Komentēšana pieejama visiem.
Jur, 21.11.2008. 18:40:03 (ip:87.110.51.190)
Komentāra reitings: 0

vai tajaa faila ir visi ir visi faili kas taja http://web.hc.lv/piemeri/file-upload-progress-bar/upload.php ?
jo man strada uploads bet nezinu kur saglaba failu un nerada progresu

Pipuks, 01.02.2009. 22:15:29 (ip:82.131.27.209)
Komentāra reitings: 0

Denis, noņem apakšā xHTML un CSS validācijas ikoniņas. Nevalidējas ne viens, ne otrs. :)

d2s, 26.02.2009. 00:14:55 (ip:80.233.128.162)
Komentāra reitings: 0

Taga validējas atkal ;)

jan (direktorss@inbox.lv), 16.06.2009. 17:31:42 (ip:86.163.213.231)
Komentāra reitings: 0

Man ne suuda nenotiek. Kur saglabaa failu progresu nesaada .Ai nekas te nesanaak :(

deni2s, 09.08.2011. 08:00:49
Komentāra reitings: 0

http://www.phpriot.com/articles/php-ajax-file-uploads

Komentāra pievienošana

Ar * atzīmētie lauciņi ir jāaizpilda obligāti.





atpakaļ uz rakstu sarakstu

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
ienāktreģistrēties