Как сделать счетчик уникальных скачиваний файлов
Возникли трудности с реализацией скрипта, который читает файл статистики скачиваний и подсчитывает количество скачиваний по каждому файлу. Полученную информацию планируется выводить на страницах возле ссылок для скачивания на соответствующие файлы. Вот мой код:
index.php
<html>
<head>
<title></title>
</head>
<body>
<a href="script.php?click=file1.txt" download="file1.txt" >Файл 1</a>
<p>Количество скачиваний: , $counter_file1</p> </br>
<a href="script.php?click=file2.txt" download="file2.txt" >Файл 2</a>
<p>Количество скачиваний: , $counter_file2</p> </br>
<a href="script.php?click=file3.txt" download="file3.txt" >Файл 3</a>
<p>Количество скачиваний: , $counter_file3</p> </br>
</body></html>
script.php
<?php
if(isset($_GET['click']))
{
$ip = $_SERVER['REMOTE_ADDR'];
$data = sprintf("файл:%s, дата:%s, ip:%s \r\n",$_GET["click"], date("d.F.Y"), $ip);
file_put_contents('counter.txt', $data, FILE_APPEND );
header("location:".$_GET["click"]);
}
?>
Пример записи в файл: файл:file3, дата:22.May.2020, ip:127.0.0.1
как сделать такой срипт?
Ответы (1 шт):
Такую информацию, как вам нужна, лучше хранить в базе данных. Это проще и надежнее. Если все же будете хранить в файле, нужно учесть следующие моменты. Данных будет много и необходимо их как-то разделять. Для этого нужно взять какой-нибудь символ (| или # или любой другой) и использовать его для сепарации. Пользоваться строго только им, иначе при разборе данных файла все собьется. Пример строки для записи в файл: book.txt|1590261980|190.163.47.135
Так же нельзя менять последовательность значений в строке (например, идет имя файла, потом временная метка, потом ip).
При записи в файл данных о скачивании обязательно в конец строки доклеивайте спецсимвол перевода строки. Это лучше делать с помощью константы PHP_EOL.
Дату и время скачивания лучше хранить в виде временной метки, получаемой с помощью функции time().
Для того чтоб использовать хранящихся в файле данные, их нужно получить, а потом распарсить для удобства. Пример, как может выглядеть функция для записи данных из файла в виде двумерного массива:
function getInfoFromFile($file){
return array_map(function($el){
return explode('|', $el);
}, file($file));
}
В качестве разделителя использован символ |. Но с таким массивом работать неудобно, поэтому полученные данные лучше переформатировать:
function parseInfo($arr)
{
foreach ($arr as $v) {
$res[$v[0]]['file_name'] = $v[0];
$res[$v[0]]['visited_at'][] = $v[1];
$res[$v[0]]['user_ip'][] = trim($v[2], PHP_EOL);
$res[$v[0]]['downloads_cnt'] = count($res[$v[0]]['user_ip']);
}
return array_values($res);
}
Теперь можно получить удобный для работы массив с нужной нам информацией:
$res = parseInfo( getInfoFromFile( __DIR__.'/info.txt' ) ); print_r($res);
Array
(
[0] => Array
(
[file_name] => book.txt
[visited_at] => Array
(
[0] => 1590087485
[1] => 1590261980
)
[user_ip] => Array
(
[0] => 188.163.47.1
[1] => 190.163.47.135
)
[downloads_cnt] => 2
)
[1] => Array
(
[file_name] => nature.jpg
[visited_at] => Array
(
[0] => 1590174208
)
[user_ip] => Array
(
[0] => 188.163.47.255
)
[downloads_cnt] => 1
)
)
Теперь используем данные из массива для вывода на страницу нужного контента:
<ul>
<?php foreach ($res as $v) : ?>
<li>
<a href="http://mysite/?script.php?click=<?php echo $v['file_name'] ;?>"><?php echo $v['file_name']; ?></a>
<span>(скачиваний - <?php echo $v['downloads_cnt']; ?>)</span>
</li>
<?php endforeach; ?>
</ul>
Получаем список со ссылками на файлы и информацией:
- book.txt (скачиваний - 2)
- nature.jpg (скачиваний - 1)
Код, отвечающий за запись в файл лучше немножко подправить:
if(isset($_GET['click'])){
$fileName = filter_input(INPUT_GET, 'click', FILTER_SANITIZE_SPECIAL_CHARS);
$time = time();
$ip = $_SERVER['REMOTE_ADDR'];
$str = $fileName . '|' . $time . '|' . $ip . PHP_EOL;
file_put_contents( __DIR__ . '/counter.txt', $str, FILE_APPEND );
header('Location: /' . $fileName);
}
Для админки можно вывести данные в виде таблицы:
<table>
<tr>
<th>File</th>
<th>date</th>
<th>ip</th>
<th>downloads</th>
</tr>
<?php foreach ($res as $v) : ?>
<tr>
<td><?php echo $v['file_name']; ?></td>
<td><?php echo implode( '<br>', array_map( function($x){
return date("d.m.Y h:m:s", $x);
}, $v['visited_at'] ) ); ?></td>
<td><?php echo implode('<br>', $v['user_ip']); ?></td>
<td><?php echo $v['downloads_cnt']; ?></td>
</tr>
<?php endforeach; ?>
</table>
<style>
table, tr, td, th {
border: 1px solid #aaa;
}
tr, td {
padding: 5px;
}
</style>
Так же есть и другие способы работы с файлами (можно считывать построчно, по байтам), почитайте статьи. Так же для хранения данных существует CSV формат (https://ru.wikipedia.org/wiki/CSV), в php есть функция для удобной работы с ним https://www.php.net/manual/ru/function.fgetcsv.php. Может это вам больше понравится.
