webrebel html css javascript laravel oop php mysql wordpress kurz

Upload progressbar s PHP a jQuery

napísal , 1 Nov 2010 [ JavaScript jQuery PHP Tutoriály ]

upload progressbar

Pri uploadovaní cez HTML formulár, hlavne ak sa jedná o veľké súbory, môže byť problém, že používateľ nevie aká časť zo súboru sa uploadla, či sa súbor vôbec uploaduje a prinajhoršom si myslí, že sa vôbec nič nedeje a nervózne kliká na submit. Ešte horšie ako zvýšená záťaž na server, ktorú generuje, je riziko, že sa na celú stránku vyserie, lebo si myslí, že nefunguje. :)

V tomto tutoriale si povieme ako za pomoci PHPčka a jQuery jednoducho vytvoriť progress bar, ktorý sa priebežne obnovuje podľa množstva prenesených dát z uploadovaných súborov a snáď pomôže predísť úniku netrpezlivých používateľov zo stránky.

Aby ste vedeli o čom je reč, tu si môžete pozrieť demo.

Na celú túto srandu v prvom rade potrebujete mať na serveri nainštalovaný PHP modul s názvom uploadprogress. Bohužiaľ sú dostupné len zdrojáky, takže ak ich nemáte ako skompilovať alebo nemáte prístup k serveru kde je tento modul už pridaný, ste pretty much fucked. :) Pod Linuxom by sa mali dať inštalovať rozšírenia cez PECL, čo som zatiaľ neskúšal a pod Windowsom ich treba kompilovať, čo je zase neskutočný pain na to, že chceme vlastne len poondený progress bar. :p

Príncíp nášho uploadera je taký, že v Javascripte zachytíme udalosť kedy sa odošle formulár (onsubmit) a spustíme funkciu, ktorá každých pár sekúnd počas odosielania súborov zisťuje informácie o priebiehajúcom uploade a zobrazuje ich.

<form action="upload_finished.php" method="post" enctype="multipart/form-data"
id="upload_form">
	<h1>brm.sk / upload progress bar demo</h1>
	
	<input id="progress_key" name="UPLOAD_IDENTIFIER" type="hidden"
	value="<?= md5( microtime().rand() ) ?>">
	
	<div id="attachments">
		<p>Uploadni súbor: <input type="file" name="attachment"></p>
		<div style="text-align: right;"><input type="submit"></div>
	</div>
	
	<div id="uploadprogress" style="display: none;">
		Uploadujú sa súbory...
		<div class="progress_border">
			<div id="progress"><!-- --></div>
		</div>
		<p id="progress_txt">Zostáva: ?</p>
	</div>
	
</form>

Fromulár je jednoduchý a jediná neštandardná vec na ňom je pole UPLOAD_IDENTIFIER obsahujúce náhodnú hodnotu, ktorá slúži pre modul uploadprogress, aby sme si podľa neho vedeli vypýtať informácie o našom uploade.

V JavaScripte sa dejú o niečo zaujímavejšie veci:

$(function()
{
	new Image().src = "progressbar.png";
	
	$('#upload_form').submit(function()
	{
		if ($("#uploadprogress").is(":visible")) return false;

		if ($("#attachments input[type=file]").val().length > 0)
		{
			$("#attachments").hide();
			$("#uploadprogress").show();
			setInterval(get_upload_progress, 2000);
		}
		else
		{
			alert("Vyber súbor, ktorý sa má uploadnúť!");
			return false;
		}
	});

	$("#progress").css("width", "0px"); // bez tohoto by nefungovala animacia progressbaru v novej Opere s novym jQuery (wtf)
});

function get_upload_progress()
{
	$.get("uploadprogress.php", { id: $("#progress_key").val() },
	function(data)
	{
		if (!data) return;
		$("#progress").stop().animate(
		{width: Math.round(100 * (data.bytes_uploaded / data.bytes_total))+"%"},
		200);
		
		var min = Math.floor(data.est_sec / 60);
		var sec = (data.est_sec % 60)+'';
		if (sec.length == 1) sec = "0"+sec;
		
		$("#progress_txt").html("Zostáva "+min+":"+sec
		+" (aktuálna rýchlosť: "+Math.round(data.speed_last/1024)+"kB/s)");
	}, 'json');
}

Najskôr sa preloadne obrázok progress baru, keďže po odoslaní formulára by sa už v niektorých prehliadačoch nenačítal. Nasleduje funkcia, ktorá sa zavolá pri odoslaní formulára (či už kliknutím na tlačítko submit alebo stlačením enteru) a má za úlohu 3 veci.

  • Skontrolovať, či už neprebieha upload a v prípade, že áno, zamedziť opätovnému odoslaniu formulára.
  • Skontrolovať, či bol vybraný súbor na uploadovanie.
  • A ak je všetko v poriadku, nakoniec skryť formulár, zobraziť namiesto neho progress bar a odpáliť ajax funkciu, ktorá ho bude každé 2 sekundy obnovovať.

Funkcia obnovujúca údaje o uploade posiela ajax požiadavky s IDčkom UPLOAD_IDENTIFIER, dostane údaje formátované ako JSON a na základe nich zmení šírku progress baru (v percentách) plus vypíše naformátované kecy o zostávajúcom čase a rýchlosti.

Na server už treba umiestniť už len jednoduchý skript, ktorý vracia údaje v spomínanom formáte JSON:

<?php
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Thu, 01 Jan 1970 00:00:00 GMT");
 
if ($_GET['id'])
{
	echo json_encode(uploadprogress_get_info($_GET['id']));
}
?>

Prvé 2 riadky zabezpečia aby prehliadač nepoužíval cache a vždy načítal čerstvé údaje a funkcia uploadprogress_get_info() vracia informácie o uploade - presnejšie: time_start (čas začatia uploadu), time_last (aktuálny čas), speed_average (priemerná rýchlosť), speed_last (posledná meraná rýchlosť), bytes_uploaded, bytes_total, files_uploaded a est_sec (odhad zostávajúceho času).

Tu nájdete celý zdroják: source.rar.

napísal , 1 Nov 2010

6 komentárov

komentuj
  1. Jozef [ Utorok 8.3.2011, 00:39 ]

    Chcel by som sa spitat ze kam uklada uploudnute subory nemozem ich nikde na servrey najst.A jqery je free?

  2. 81403 [ Utorok 8.3.2011, 10:40 ]

    PHP uklada subory do tempu a v tomto kode s nimi nic dalej nerobime.. cize musis ich potom este premiestnit - http://www.php.net/manual/en/features.file-upload.post-method.php
    Jasne, jQuery je zadara, dokonca ho nemusis ani stahovat, kedze sa nacitava priamo z CDN.

  3. cvirooo [ Nedeľa 17.7.2011, 14:37 ]

    zdravím,
    skúšal som to demo, ale v prehliadači Chrome v. 12.0.742.122 mi to nechce ísť, vo Firefoxe, Opere, IE ide všetko OK, neviete kde by mohol byť problém?

  4. 81403 [ Nedeľa 17.7.2011, 15:18 ]

    Hmm, fakt nejde, uz ani Chrome nie je to, co byval :D
    Po odoslani formulara Chrome nejako nechce robit AJAXove requesty a s tym sa moc neda robit. Teda dalo by sa to cez iframe, ale to je zbytocne zlozite.

    Alternativnym riesenim je napriklad http://valums.com/ajax-upload/ advanced uploadovac, ktory zase ukazuje progress len vo FF, Chrome a Safari :) Navyse sa fakt zle customizuje.

  5. anton [ Štvrtok 4.8.2011, 09:22 ]

    no tak už to nefunguje ani v opere ani vo ff

  6. PayteR [ Piatok 31.8.2012, 05:39 ]

    Toto som už raz využil a je to podla mňa naprd :P zbytočne komplikované a použiteľné iba na serveri, kde si môžeš inštalovať moduly do PHP ... lepšie je radšej použiť nejaký jQuery upload plugin, ktorý aj keď v IE to nebude davat percenta