Transparentny licznik pobrań

Pytanie nieco zawiłe, chciałbym sobie liczyć pobrania pliku. Najprościej umieszczać link do skryptu php który po podliczeniu robi redirect do fizycznego pliku. Tylko tutaj zaczynają się schody, gdyż łatwo dojść do prawdziwej ścieżki i ją zlinkować z pominięciem skryptu.

Wymyśliłem coś takiego: podaje na stronie bezpośredni link do pliku, przy pomocy mod_rewrite robię przekierowanie na php, ten liczy i z powrotem przekierowywuje na plik, i teraz problem, co zrobić aby za drugim razem mod_rewrite nie zadziałał (bo powstała by nieskończona pętla). Moje myśli kierują się w kierunku wysłania jakiegoś nagłówka a później warunku w rewrite… ma ktoś jakiś pomysł?

Ew. można jeszcze wyrzucić zawartość pliku tak jak w przykładach tutaj: http://php.net/manual/en/function.header.php, tylko czy w momencie gdy ktoś będzie pobierał plik dłużej niż max. czas wykonywania skryptu nie nastąpi jego przerwanie?

Chwilę mi to zajęło, ale chyba znalazłem rozwiązanie. Po kolei:

-> użytkownik aktywuje link do pliku

-> mod_rewrite sprawdza typ żądania i jeśli jest podstawowy to przekierowuje go na skrypt zliczający pobrania

-> skrypt zlicza aktywację linku i wysyła dowolną zmienną metodą POST przez curl na adres pliku

-> mod_rewrite sprawdza, jaka jest metoda żądania i jeśli jest to POST, to przekierowuje na pobierany plik

RewriteCond %{REQUEST_METHOD} ^POST$

RewriteRule ^plik.txt$ plik.txt [L]


RewriteRule ^plik.txt$ zlicz.php [L]

Jeszcze można byłoby sprawdzić, czy żądanie POST przychodzi z Twojego serwera.

Z moich skromnych testów wynika, że to działa ;-).

Dobre, nawet bardzo :slight_smile: Dzięki, zaraz potestuje w warunkach bojowych.

Ja używam czegoś takiego :

<? 

if (!empty($_GET['plik'])) {

	$plik = 'sciezka/do/plikow/'.$_GET['plik'];

	if (file_exists($plik)){

		$dane = 'licznik/licz_'.$_GET['plik'].'.txt';

		if (file_exists($dane)){

			$aa = fopen($dane, "r"); 

			$licznik = trim(fgets($aa, 1024)); 

			fclose($aa);

		} else $licznik = 0;

		$licznik++;

		$aa = fopen($dane, "w");

		fputs($aa, $licznik);

		fclose($aa);

		$file = escapeshellarg($plik);

		$typ = shell_exec("file -bi " . $file);

		header('Content-Disposition:attachment; filename="'.$plik.'"');

		header("Content-Transfer-Encoding: Binary");

		header('Content-length: '.filesize($plik));

		header('Content-type:'.$typ);

		header("Connection: Close");

		readfile($plik);

	} else echo 'brak pliku';

} else {

	header('Location:index.php');

}

?>

Nie wiem czy to w zupełności rozwiązuje problem i czy w pełni jest to bezpieczne ( pod obojętnie jakim względem ). Z tego co się orientuję też nie wiadomo jaka jest bezpośrednia ścieżka do pliku.

Krytyka mile widziana

Tak, ale co jeśli ktoś pobiera plik dłużej niż czas wykonania skryptu (max_execution_time)? Ma to sens dla drobnych plików…