Zobrazení průběhu uploadu prakticky
Možnosti pro zobrazení indikátoru, který by uživateli zobrazoval průběh odesílání formulářových dat (a především souborů v nich), jsem již rozebíral, nyní bych se rád zaměřil na praktickou ukázku v PHP 5.2.0 a novějším spolu s rozšířením APC. Ještě než se podíváme na ukázku kódu, musím si postesknout nad tím, že informaci o průběhu odesílání dat nezobrazuje přímo prohlížeč. Na rozdíl od situace při stahování dat má přesnou informaci o tom, kolik dat celkem je a jak je s jejich posíláním daleko.
Pokud je zapnuta konfigurační direktiva apc.rfc1867 a formulář obsahuje pole APC_UPLOAD_PROGRESS
, tak bude APC při přenášení všech následujících souborů ve formuláři aktualizovat sdílenou proměnnou upload_key
, kde key je hodnota zmíněného formulářového pole. K této proměnné můžeme následně přistoupit ze všech skriptů funkcí apc_fetch.
Pokud chceme průběh nahrávání souboru zobrazovat přímo ve stránce s formulářem, dá se to nejpohodlněji zařídit pomocí technologie AJAX. V pravidelných intervalech se budeme serveru dotazovat na stav přenosu a tuto informaci budeme zobrazovat na stránce.
<?php
$id = uniqid();
?>
<script type="text/javascript">
function progress_update(xmlhttp) {
if (xmlhttp.readyState == 4) {
document.getElementById('progress').innerHTML = xmlhttp.responseText;
window.setTimeout(progress_send, 1000);
}
}
function progress_send() {
send_xmlhttprequest(progress_update, 'GET', 'progress.php?id=<?php echo $id; ?>');
}
</script>
<form action="" method="post" enctype="multipart/form-data">
<input type="hidden" name="APC_UPLOAD_PROGRESS" value="<?php echo $id; ?>">
<input type="file" name="file">
<input type="submit" onclick="window.setTimeout(progress_send, 1000);">
<span id="progress"></span>
</form>
Viz send_xmlhttprequest
.
Pro identifikátor přenosu by se dalo použít např. session_id, nicméně pro případ, že by jeden uživatel odesílal více formulářů, je lepší použít nějaký zcela jednoznačný identifikátor.
Pravidelná aktualizace stavu přenosu svádí k použití funkce setInterval, u té bychom ale museli řešit případ, kdy se vyřízení dřívějšího požadavku chvíli pozdrží, takže jeho odpověď potom přepíše aktuálnější hodnotu. Proto budeme znovu čekat až poté, co se zobrazí předchozí stav.
Skript pro vracení dat už bude poměrně jednoduchý – z informací v poli upload_$_GET[id]
vypočteme procento přenesených dat a vypíšeme ho.
<?php
$progress = apc_fetch("upload_$_GET[id]");
echo ($progress ? number_format(100 * $progress["current"] / $progress["total"], 2) . "%" : "");
?>
Pokud bychom chtěli zobrazovat i další údaje, vrátili bychom XML soubor nebo JSON data se všemi informacemi – pole obsahuje kromě celkového objemu dat a už přenesené velikosti také položky pro přenosovou rychlost (rate
), název formulářového pole (name
), dočasnou cestu (temp_filename
) a původní jméno právě přenášeného souboru (filename
) a také informace o zrušeném přenosu (cancel_upload
) a dokončení (done
).
Při pokusech s odesíláním velkých souborů nezapomeňte správně nastavit maximální velikost nahrávaných souborů.
Diskuse
> musím si postesknout nad tím, že informaci o průběhu odesílání dat nezobrazuje přímo prohlížeč
A já se musím pochlubit, že můj prohlížeč to zobrazuje. Opera, když si nastavím Zobrazit -> Lišty -> Přizpůsobit -> Průběh načítání: Pod načítanou stránkou.
23.4.2007 13:29:53
Matěj:
Dobrý den, když si stáhnu soubory APC-3.1.4 jak to mam nainstalovat, nebo prostě rozchodit? Není k tomu někde nějakej návod jak to apc nainstalovat a používat?
Děkuji
9.9.2010 19:24:36
Firefox 3.0 by to již měl umět také.
23.4.2007 17:04:45
Neni v tom druhem snippetu chybicka?
$progress = apc_fetch("upload_$_GET[id]");
->
$progress = apc_fetch("upload_{$_GET[id]}");
?
25.4.2007 18:30:32
To jsem se asi trochu unahlil, PHP to zkousne, ale ja bych to preci jen napsal takhle:
$progress = apc_fetch("upload_{$_GET['id']}");
25.4.2007 18:32:23
Chybný by byl naopak způsob "upload_{$_GET[id]}", protože by se v něm id bralo jako konstanta. Když už, tak "upload_{$_GET["id"]}" nebo spíš rovnou "upload_" . $_GET["id"], ale je to samoúčelné, "upload_$_GET[id]" je zcela v pořádku.
25.4.2007 18:46:54
Ano, PHP by vyhodilo notice, mel jsem za to, ze ho hodi i pri tom vasem zpusobu zapisu, ale neni tomu tak.
Kazdopadne diky za zajimavy clanek, rozhodne si to vyzkousim.
25.4.2007 19:42:02
Tomáš Müller:
Takze jsem zpet, nyni ale doufam, ze muj komentar bude skutecne k veci a prinosny :)
Pokud instalujete APC jenom pro tuhle featuru, doporucuji upravit konfiguraci. Zejmena apc.shm_size - ta urcuje, jakou velikost ma jeden segment shared memory pouzivane pro cache. Defaultni hodnota je 30 a je to v megabajtech :) apc.shm_segments je pocet alokovanych segmentu, default je jeden.
11.5.2007 00:45:38
tygr:
Muzete mi prosim poradit, kde najdu konfiguracni direktivu apc.rfc1867, kde ma byt umisten skript pro vraceni dat a zda na zprovozneni podpory APC v PHP staci v php.ini pridat extension=php_apc.dll?
12.7.2007 11:37:06
Filip Krejčí:
Problem je ale v tom ze apc.rfc1867 neni thread safe, a posledni upload rusi stavy vsech predchozich. Tudiz je to cele o nicem.
17.10.2007 20:15:52
Vlastovka:
Dobrý den,
Rád bych věděl, zda se nějak může uploadovat více souborů v 1 formuláři (resp. jak predat id vice souboru v 1 formulari - zde je jen 1 pole s nazvem APC_UPLOAD_PROGRESS)
díky
5.8.2008 04:25:25
Pokud vím, tak ne.
5.8.2008 05:20:31
Andy:
Ovsem ze jde, staci formular upravit napriklad takto <input type="hidden" name="APC_UPLOAD_PROGRESS" value="nejaky id" />
<input type="file" name="file[]" />
<input type="file" name="file[]" />
apc_fetch() pak bude zobrazovat celkovy progress upload a prave uploadovany soubor napriklad
array(6) {
["total"]=>
int(627270)
["current"]=>
int(41326)
["filename"]=>
string(12) "PUTTYGEN.EXE"
["name"]=>
string(6) "file[]"
["done"]=>
int(0)
["start_time"]=>
float(1240498405.4505)
}
jak zjistit prubeh uploadu aktualniho souboru sem zatim nezjistoval, pripadne pro upload vice souboru lze udelat vice formularu a pomoci javascriptu je odesilat postupne :-)
23.4.2009 10:55:42
tomasr:
Je nejake omezeni pro to APC na strane serveru? Kdyz sem to zkousel, tak behem uploadu se nedelo nic, az nakonci skocilo 100%, zadnej progress neni videt:(.
15.4.2009 07:16:08
Andy:
Mám stejný problém, funkce apc_fetch() po celou dobu uploadu nic nevrací až po dokončení uploadu vrátí výsledek.
23.4.2009 10:44:41
Andy:
Uz vim cim to je, je treba uvest
<input type="hidden" name="APC_UPLOAD_PROGRESS" value="id" />
PRED POLEM
<input type="file" name="file" />
protoze prohlizec posila jednotliva pole za sebou stejne jak jsou uvedena na strance, to znamena, pokud uvedete APC_UPLOAD_PROGRESS az za file, prohlizec posle id az po uploadu souboru
23.4.2009 10:49:49
Zapl jsem direktivu apc.rfc1867 a formulář obsahuje pole APC_UPLOAD_PROGRESS přesto mi apc_fetch nic nevrátí. Může někdo poradit? (phpinfo APC module =
http://www.srdcari.cz/info.php#module_apc )
25.4.2011 17:57:09