跟踪直接文件下载的最佳方法是什么?我找到了一些解决方案,例如这个:
http://www.gayadesign.com/diy/download-counter-in-php-using-htaccess/
但它对我不起作用,当我试图下载文件时,我只得到一个空白页面+我不知道它是否足够安全......
Google Analytics仅适用于javascript,无法跟踪直接文件下载。
Best是一个安全且自己的托管解决方案。
答案 0 :(得分:10)
随意使用:)
<强> htaccess的:强>
RewriteEngine on
RewriteRule ^(.*).(rar|zip|pdf)$ http://xy.com/downloads/download.php?file=$1.$2 [R,L]
<强> MySQL的:强>
CREATE TABLE `download` (
`filename` varchar(255) NOT NULL,
`stats` int(11) NOT NULL,
PRIMARY KEY (`filename`)
)
<强>的download.php 强>
<?php
mysql_connect("localhost", "name", "password")
or die ("Sorry, can't connect to database.");
mysql_select_db("dbname");
$baseDir = "/home/public_html/downloads";
$path = realpath($baseDir . "/" . basename($_GET['file']));
if (dirname($path) == $baseDir) {
if(!is_bot())
mysql_query("INSERT INTO download SET filename='".mysql_real_escape_string(basename($_GET['file']))."' ON DUPLICATE KEY UPDATE stats=stats+1");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=" . basename($_GET['file']));
header("Content-Length: ".filesize($path));
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: binary");
ob_clean();
ob_end_flush();
readfile($path);
}
function is_bot()
{
$botlist = array("Teoma", "alexa", "froogle", "Gigabot", "inktomi",
"looksmart", "URL_Spider_SQL", "Firefly", "NationalDirectory",
"Ask Jeeves", "TECNOSEEK", "InfoSeek", "WebFindBot", "girafabot",
"crawler", "www.galaxy.com", "Googlebot", "Scooter", "Slurp",
"msnbot", "appie", "FAST", "WebBug", "Spade", "ZyBorg", "rabaz",
"Baiduspider", "Feedfetcher-Google", "TechnoratiSnoop", "Rankivabot",
"Mediapartners-Google", "Sogou web spider", "WebAlta Crawler","TweetmemeBot",
"Butterfly","Twitturls","Me.dium","Twiceler");
foreach($botlist as $bot)
{
if(strpos($_SERVER['HTTP_USER_AGENT'],$bot)!==false)
return true; // Is a bot
}
return false;
}
?>
来源 - gayadesign.com
答案 1 :(得分:3)
你的apache日志应该包含很多信息,但我认为你要求的是更多地控制记录的内容和时间。所以你想要做的是有两个页面:一个带有文件的链接,另一个带有跟踪文件的页面,如下所示:
<强> file_page.php 强>
<a href="download.php?id=1234">Download File!</a>
<强>的download.php 强>
<? // Code to track the file using PHP, whether that means storing data in a database, saving to a log, or emailing you. I'd use a DB, like so:
// Prep the vars
$file_id = $_GET['file_id']; // You should sanitize this first.
$file_path = '/files/'.$file_id.'.pdf';
// Save data to database
mysql_query('INSERT INTO download_log
SET file_id = '.$file_id.',
date_downloaded = '.date('Y-m-d H:i:s').',
user_id = '.$_SESSION['user_id']);
// Now find the file and download it
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename='.$file_id.'.pdf); // or whatever the file name is
readfile($file_path);
无论如何都是这样的。
完成后页面将为空白,但所有浏览器都应在页面加载时开始下载文件。
所以我在这里做的是保存文件ID,当前日期时间以及下载它的人的用户ID(来自$ _SESSION变量)。您可能希望存储更多信息,例如用户的IP地址,HTTP_REFERRER或其他$ _SERVER信息,以便您可以跟踪用户的来源以及他们下载的时间和内容。
祝你好运。答案 2 :(得分:0)
为了使代码与PHP7.3,Mysqli和Mariadb引擎一起使用,我对原始答案进行了两项修改:
2:Mariadb SQL在“ UPDATE”之后不接受“ SET”,因此我使用了“ ON DUPLICATE KEY UPDATE stats = stats + 1”
结果,我在这里发布了一个新问题:Download counter for direct download links using .htaccess, mysql and php
请参阅下面的完整代码...
<?php
$conn = mysqli_connect('localhost', 'user_name', 'password','database');
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
$baseDir = '/home/user/domains/mydomain.com/public_html/downloads';
$path = realpath($baseDir . '/' . basename($_GET['file']));
$file = basename($_GET['file']);// this is what I used instead mysqli_real_escape_string
$sql = 'INSERT INTO downloads VALUES ("'.$file.'", 1) ON DUPLICATE KEY UPDATE stats = stats + 1';
//***************************************************
// following SQL line inserts record with empty filname field value but updates the counter as it is supposed to:
// $sql = 'INSERT INTO download VALUES ('.mysqli_real_escape_string(basename($_GET['file'])).", 1)' ON DUPLICATE KEY UPDATE stats=stats+1";
//**********************************************************
if (dirname($path) == $baseDir) {
if(!is_bot())
mysqli_query($conn,$sql);
mysqli_close($conn);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=" . basename($_GET['file']));
header("Content-Length: ".filesize($path));
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: binary");
ob_clean();
ob_end_flush();
readfile($path);
}
function is_bot()
{
$botlist = array("Teoma", "alexa", "froogle", "Gigabot", "inktomi",
"looksmart", "URL_Spider_SQL", "Firefly", "NationalDirectory",
"Ask Jeeves", "TECNOSEEK", "InfoSeek", "WebFindBot", "girafabot",
"crawler", "www.galaxy.com", "Googlebot", "Scooter", "Slurp",
"msnbot", "appie", "FAST", "WebBug", "Spade", "ZyBorg", "rabaz",
"Baiduspider", "Feedfetcher-Google", "TechnoratiSnoop", "Rankivabot",
"Mediapartners-Google", "Sogou web spider", "WebAlta Crawler","TweetmemeBot",
"Butterfly","Twitturls","Me.dium","Twiceler");
foreach($botlist as $bot)
{
if(strpos($_SERVER['HTTP_USER_AGENT'],$bot)!==false)
return true; // Is a bot
}
return false;
}
function alert($msg) {
echo "<script type='text/javascript'>alert('$msg');</script>";
}
?>
答案 3 :(得分:0)
我也对这里发布的原始代码进行了一些改进。 我添加了一些额外的统计数据,例如国家、地区、纬度和经度,仅举几例...
这是更新的代码:
<?php
$conn = mysqli_connect('localhost', 'aeon_dl_usr', 'Turions@1522','aeon_downloads');
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
if($_GET['f']=="workbook"){
$file="work_log_book_public.pdf";
}else{
die("File not found.");
}
$baseDir = substr(__FILE__,0,strpos(__FILE__,"downloads"))."downloads/";
$path = realpath($baseDir . '/' . $file);
$ipAddress=get_client_ip();
$geo = unserialize(file_get_contents("http://www.geoplugin.net/php.gp?ip=".$ipAddress));
$User_Ipaddress=$geo["geoplugin_request"];
$User_Country = $geo["geoplugin_countryName"];
$User_City = $geo["geoplugin_city"];
$User_Region = $geo["geoplugin_region"];
$User_CurrencySymbol = $geo["geoplugin_currencySymbol"];
$User_CurrencyCode = $geo["geoplugin_currencyCode"];
$User_Latitude = $geo["geoplugin_latitude"];
$User_Longitude = $geo["geoplugin_longitude"];
$sql = 'INSERT INTO downloads VALUES ("'.$User_Longitude.'", "'.$User_Latitude.'","'.$User_CurrencyCode.'","'.$User_CurrencySymbol.'","'.$User_Region.'","'.$User_City.'","'.$User_Country.'","'.$User_Ipaddress.'", "'.$file.'", 1) ON DUPLICATE KEY UPDATE stats = stats + 1';
if (dirname($path) == $baseDir) {
if(!is_bot()){
mysqli_query($conn,$sql);
mysqli_close($conn);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=".$file);
header("Content-Length: ".filesize($path));
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: binary");
ob_clean();
ob_end_flush();
readfile($path);
}
}else{
die("error on loading file");
}
function is_bot(){
$botlist = array("Teoma", "alexa", "froogle", "Gigabot", "inktomi",
"looksmart", "URL_Spider_SQL", "Firefly", "NationalDirectory",
"Ask Jeeves", "TECNOSEEK", "InfoSeek", "WebFindBot", "girafabot",
"crawler", "www.galaxy.com", "Googlebot", "Scooter", "Slurp",
"msnbot", "appie", "FAST", "WebBug", "Spade", "ZyBorg", "rabaz",
"Baiduspider", "Feedfetcher-Google", "TechnoratiSnoop", "Rankivabot",
"Mediapartners-Google", "Sogou web spider", "WebAlta Crawler","TweetmemeBot",
"Butterfly","Twitturls","Me.dium","Twiceler");
foreach($botlist as $bot)
{
if(strpos($_SERVER['HTTP_USER_AGENT'],$bot)!==false)
return true; // Is a bot
}
return false;
}
function alert($msg) {
echo "<script type='text/javascript'>alert('$msg');</script>";
}
function get_client_ip() {
$ipaddress="";
if (isset($_SERVER['HTTP_CLIENT_IP']))
$ipaddress = $_SERVER['HTTP_CLIENT_IP'];
else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
$ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
else if(isset($_SERVER['HTTP_X_FORWARDED']))
$ipaddress = $_SERVER['HTTP_X_FORWARDED'];
else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
$ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
else if(isset($_SERVER['HTTP_FORWARDED']))
$ipaddress = $_SERVER['HTTP_FORWARDED'];
else if(isset($_SERVER['REMOTE_ADDR']))
$ipaddress = $_SERVER['REMOTE_ADDR'];
else
$ipaddress = 'UNKNOWN';
return $ipaddress;
}
?>