ugrás a tartalomhoz

Letöltés számláló

ThomasEdison · 2007. Nov. 16. (P), 17.41
Helló!
A segítségeteket szeretném kérni a következőben:
Készítettem egy php script-et, amivel fájlokat lehet letölteni. Szeretnék bele egy olyat tenni, hogy számolja, hányszor töltötték le az adott fájl. Ezt mind sikerült is megcsinálno, azonban ha egy letöltés megszakad, azt is beleszámolja, én viszont olyat szeretnék, hogy csak a teljesen befejezett letöltések legyenek számlálva. Próbálkoztam a connection_aborted() függvénnel, mint az alábbi kódban látható, de mégse működik helyesen.

<?php
ignore_user_abort(TRUE);
set_time_limit(0);

require_once('../functions.php'); // mysql_encode és mysql_decode függvényeket tartalmazza

$sql = @mysql_connect('localhost', '***', '***');
@mysql_select_db('***');
@mysql_query("SET NAMES 'latin2'");

// van-e ilyen letölthető fájl
$query = "SELECT download_file FROM downloads WHERE download_file = '".mysql_encode($_GET['file'],$sql)."'";
$result = mysql_query($query);
if (mysql_num_rows($result) !== 1)
  die("The requested file could not be found");
$row = mysql_fetch_row($result);
@mysql_free_result($result);
$filename = realpath(mysql_decode($row[0]));

// nem lehet php kiterjesztésű
if(strToLower(substr($filename,strlen($filename)-3, 3) == 'php')) {
	die( "The requested file cannot be retrieved for security reasons.");
}

// A fájl nem található
if(!file_exists($filename)) {
	die("The requested file could not be found");
}

// required for IE, otherwise Content-disposition is ignored
if(ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); }


// ne legyen cache-selve
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);

// fájl típusa
$ext = strToLower(substr($filename,strlen($filename)-3, 3));
if ($ext == "mp3" ) { header("Content-Type: audio/x-mp3"); } 
else if ($ext == "jpg") { header("Content-Type: image/jpeg"); }
else if ($ext == "gif") { header("Content-Type: image/gif"); }
else if ($ext == "png") { header("Content-Type: image/png"); }
else if ($ext == "swf") { header("Content-Type: application/x-shockwave-flash"); }
else if ($ext == "flv") { header("Content-Type: video/flv"); }

// fájllal kapcsolatos fejlécek
header("Accept-Ranges: bytes");
header("Content-Disposition: attachment; filename=\"".basename($filename)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filename));

// fájlbeolvavása és kiküldése
$fp = fopen($filename, 'rb');
while (!feof($fp) && !connection_aborted()) {
  echo fread($fp, 1024);
  flush();
  if (connection_aborted()) {
    fclose($fp);
    die();
  }
}
fclose($fp);

// loggolás
if (!connection_aborted()) {
  $query = "UPDATE downloads SET download_counter = download_counter + 1 WHERE download_file = '".mysql_encode($_GET['file'],$sql)."'";
  mysql_query($query);
}

?>
 
1

Warningok?

vbence · 2007. Nov. 16. (P), 18.51
Ha lenne PHP hibajelzés (warning), azt látnád? Egy tipikus tömeghosting szituációban: a display_errors ki van kapcsolva, úgyhogy nem látod a warnigot, amit az ignore_user_abort generál, hogy nem működik safe módban.
2

Warningok?

ThomasEdison · 2007. Nov. 16. (P), 19.35
Megcsináltam a set_error_handler() segítségével, hogy fájlba írom a hibákat, de nem mutat semmit. A error_reporting(E_ALL) mellett se. (persze ha teszek bele hibát, akkor működik a loggolás)

Ahogy próbálkoztam tovább azt vettem észre, hogy mikor a linkre kattintok, bejön ugyebár egy ablak, hogy menteni szeretném-e a fájlt, vagy megnyitni (FF-ben és IE-ben is). És ezalatt belekukkantok a mysqlbe, akkor látom, hogy már növelte is a számláló értékét eggyel. Pedig valójában még meg sem kezdőtött a letöltés.
4

A letöltés már elkezdődött

vbence · 2007. Nov. 18. (V), 12.20
Ez nem lenne probléma, hizen a böngésző már elkezdi letölteni a háttérben a fájlt, hogy ne menjen kárba az idő, még kiválaszod a könyvtárat. Cacel-kor persze megszakítja a kapcsolatot, ekkor a szkripted elvileg die-ol, és nem fut le a query a végén.

Viszont: Ha a fájl kicsi a letöltés befejeződhet még a "Save As..." dialógusablak alatt. Ilyenkor ha cancel-t nyomsz a böngésző kidobja a már letöltött adatokat (ezesetben az egész fájlt). A usernek úgy tűnhet, hogy nem töltött le semmit, valójában már az egész fájlt letöltötte és törölte is.
5

A letöltés már elkezdődött

ThomasEdison · 2007. Nov. 18. (V), 22.35
Jaja, valószínűleg így is van, ahogy nézegettem az adatátviteli sebességet. Viszont ha megszakítom a szkript akkor is végig fut. A fájlok 8-10 megásak, úgyhogy ilyen gyorsan nem jönnek le a fájlok, amíg reagálok a dialógusablakra.
6

...

Ronyn · 2007. Nov. 19. (H), 10.00
T'án ki lehetne venni az ignore_user_abort-ot...
7

Szerintem nem hazsnálna

vbence · 2007. Nov. 19. (H), 12.53
A PHP nagyon rapszódikusan abortálja a szkripteket. Lehet, hogy még fél percig fut a szakadás után. A connection_aborted kéne legyen a mérvadó megoldás.

Esetleg érdemes lenne csinálni egy egyszerű példát. Biztos van a php manuálban valami. Ha az működik, akkor lehet közelíteni a kettőt...
3

Assz'em a safe

Ronyn · 2007. Nov. 16. (P), 21.27
mod nem befolyásolja a connection fuggvényeket,viszont az ignore_usert_abort=True pont azt jelent hogy a script hagyja figyemen kivul a kapcsolat bontást...
Az alapbeállitás esetén viszont a script is leállna ilyenkor...