Alternative PHP Cache, często zwany APC jest mechanizmem buforowania skompilowanego kodu php. Dostępny jest za darmoz repozytoriów PEAR i PECL. Pierwsze wersje pakietu była przygotowane przez Daniela Cowgilla oraz Gorge'a Schlossnagle'a i wydane przez firmę Community Connect. Po pojawieniu się PHP 5, oryginalny pakiet został zmodyfikowany przez Yahoo!, dostowując go do nowych mechanizmów Zend'a.
Działanie pakietu polega na pobieraniu ze środowiska wykonawczego skompilowanego kodu PHP i zapisywaniu go w pamięci. Przy każdym rządaniu skryptu APC sprawdza najpierw czy nie jest dostępna jego skompilowana postać, a powtórna kompilacja i wykonanie skryptu z dysku nastepuje tylko wtedy gdy w pamięci nie ma potrzebnych danych. Pozwala to na wzrost wydajności nawet czterokrotnie. My głównie wykorzystamy pakiet APC do śledzenia procesu przesyłania plików z przeglądarki do serwera WWW. Pomine więc instalację i konfiguracje samego rozszerzenia, które możemy uruchomić jako dynamiczna bibliotekę lub mieć pakiet na stałe wkompilowany w php. Najwygodniejszym sposobem jest oczywiście pierwszy, który pozwala łatwo i sprawnie w razie kłopotów wyłączyć moduł. Musimy pamietać że sam moduł zadanie ma inne niż kontrolowanie przesyłanych plików, więc cudów nie należy się spodziewać. Działający przykład z artykułu, możemy zobaczyć pod adresem: http://mephir.net.pl/upload_progress-apc/(tymczasowo nie działa, powodem jest przeniesienie serwisu na nowy serwer, potrzeba ksonfigurowania apc, co nie jest potrzebą pierwszej konieczności,za utrudnienia przepraszam).
Jak już pisałem nie będe tu mówił o pełnej procedurze instalacji i konfiguracji, ponieważ jest to zbędne. Pakiet jest dostępny dla systemu Linux oraz Widnows. Ważną kwestią jest to, że zdziebko się gryzie z mod_security serwera Apache, jak i również mod_evasive, ale tu głównie chodzi o liczbę żądań wysyłanych do serwera poprzez Ajax dla sprawdzenia postępu wysyłania pliku, więc jedyne co wystarczy zrobić to po prostu ustawić go mniej resrtykcyjnie. Najważniejszą sprawą jest abyśmy mieli włączoną obsługe rfc1867, można to zrobić dopisując na koniec php.ini, bądź jak to jest u mnie na serwerach w oddzielnym pliku apc.ini, linię:
Niestety sam formualrz z możliwością wysyłania pliku, też mus przejść mały tuning abyśmy mogli wiedzieć ile ów danych zostało już przesłane do serwera. Do samego formularza musimy dodać ukryte pole, które musi mieć odpowiednią nazwe. Domyślnie jest to APC_UPLOAD_PROGRESS. Pole te musi mieć unikalna wartość dla każdego z transferów. Możemy wykorzystac do tego zmienną sesyjną, ale również z powodzeniem wartość funckji uniqid(), która zwróci nam unikalny ciąg znaków. W przykładzie będzie wykorzystana ta druga opcja. Ja w formularzu umieściłem cztery pola input typu file i ma on postać:
Jeżeli chcemy dowiedzieć się na jakim etapie stoji nasz upload, musimy "zadać pytanie" modułowi APC o ilość otrzymanych danych. Dokonamy tego korzystając z funckji apc_fetch(), gdzie jako argument podamy identyfikator uploadu, który ma postać upload_naszunikalnyciagznakow. Wynik działania tej funckji, po paru obliczeniach zwrócimy sobie w postaci ciągu znaków JSON abyśmy dane te mogli wygodnie używać w JS. Funckja apc_fetch zwraca tablice z wartościami, jak w przykładzie:
array 'total' => int 37825474 'current' => int 41230 'filename' => string 'tw4win_pro.exe' (length=14) 'name' => string 'plik_1' (length=6) 'done' => int 0 'start_time' => float 1222799074.4788
Plik upload_progress.php będzie miał postać:
<?php
/**
* Funckja przelicza ilośc bajtów na kilo bajty oraz na megabajty w zalezności od rozmiaru pliku
*
* @param integer $bytes
* @return string
*/
function przelicz($bytes){
$kb=$bytes/1024;
$mb=$kb/1024;
if($mb<1){
return round($kb, 2).'KB';
} else {
return round($mb, 2).'MB';
}
}
/**
* Funckja przelicza ilość sekund na minuty
*
* @param integer $sek
* @return string
*/
function czas($sek){
$s=$sek % 60;
$m=(int)($sek/60);
return $m.':'.(strlen($s)==1?'0'.$s:$s);
}
if(isset($_GET['progress_key'])) {
/* Wysłanie odpowiednich nagłówków do przeglądarki, aby nie zcachowała zawartości pliku */
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
/* Pobranie stanu odebrania pliku */
$status = apc_fetch('upload_'.$_GET['progress_key']);
/* Pobranie aktualnego czasu w formacie unixtimestamp, typ danych float */
$czas=microtime(true);
/* wyliczenie czasu trwania uploadu, predkości, postałego czasu oraz stosunku procentowego wysłanych danych */
$roznica=(int)($czas-$status['start_time']);
$predkosc=$status['current']/$roznica/1024;
$pozostalo=(int)(($status['total']-$status['current'])/$predkosc/1024);
$procentowo=round((100*$status['current']/$status['total']),2);
/* utworzenie ciągu znaków json oraz wyświetlenie go */
echo json_encode(array(
'nazwapliku'=>$status['filename'], //nazwa aktualnie wysyłanego pliku
'calkowity'=>przelicz($status['total']), //całkowity rozmiar kolejki w kb lub mb
'wyslano'=>przelicz($status['current']), //ilośc przesłanych danych przeliczona na kb lub mb
'czas'=>czas($roznica), //czas trwania tranzakcji
'pozostalo'=>czas($pozostalo), //przypuszczalny czas do konca
'predkosc'=>round($predkosc,2), //predkosc transferu wyrazona w KB/s
'procent'=>$procentowo, //procent ilosci wyslanych danych
));
}
?>Pierwszą rzeczą jaka musimy zrobić to pobrać status poczatkowy transferu oraz wyświetlic warstwe progress. Zrobimy to w wyjątku submit formularza pliczki.
Alternatywą dla tego rozwiązania jest użycie niewidzialnego pliku swf, choćby korzystając z darmowego swfupload, którym też się zajmiemy. Nasze rozwiązanie, posiada swoje plusy i minusy. Na pewno dużym powodem, który przepowiada za, jest uniezalżnienie od Flash'a, jednak w serwisach, które mają dużą odwiedzalność, a nie mają za wydajnych serwerów, może to powodować problemy wydajnościowe, z powodu dużej ilości żądań wysyłanych do serwera. Innym minusem jest to, że większość infomacji o pliku i tak otrzymujemy po jego wysłaniu, więc nie bardzo możemy zablokować np. rozmiar jego, na co dla odmiany pozwala nam użycie flasha. Przykład mój można uzupełnic o takie rzeczy jak pasek postępu choćby, do czego serdecznie zachęcam.
| Załącznik | Wielkość |
|---|---|
| upload_progress-apc.zip | 19.43 KB |
hmm
Chciałem zaznaczyć że niestety nie działa :( zmienna 'upload_uid' zostaje zwrócona dopiero po zakończeniu przesyłania... nie udało mi się jej odczytać w trakcie przesyłania pliku. Live demo na http://mephir.net.pl/upload_progress-apc/ też nie działa...
Sprawdzałem działa
Sprawdzałem działa, z konfiguracją APC czasami bywają problemy, czesto lubi sie wykrzaczać, może masz js'a wyłączonego dlatego nie odświerzyło, ciężko mi powiedzieć, projekt z wykorzystaniem tego robiłem dla swojego partnera jednego, o tyle mi konfiguracja APC poszła gładko, o tyle oni na serwerach produkcyjnych nieźle się namęczyli by działało zawsze.
ort!wybacz, ale !ortografia
ort!
wybacz, ale !ortografia daje po oczach:
'żądanie', 'stoi'
polecam słownik!
z drugiej strony dobry artykuł.
pzdr.
zapisywanie
jak zrobić, żeby pliki się zapisywały i te zera zamieniały się na liczby ?
nie dziala
Nie dziala. to mial byc progressbar a z progresem to nie ma nic wspolnego.... pusty ekran i na koniec.... ze przeslano pliki.
Rowniez potwierdzam, ze
Rowniez potwierdzam, ze przedstawione demo nie dziala - a sprawdzalem na FF i Chomie.
Dodaj nową odpowiedź