Количество скачиваний файла на PHP

На одном из форумов мне задали вопрос: «Как реализовать подсчет количества скачиваний файла?». Покумекав немного я решил написать пример подобной реализации с использованием не баз данных, но файлов. И так приступим. Прежде всего надо разбить задачу на более простые подзадачи.
1) Как подсчитывать;
2) Как хранить подсчитанные данные;
3) Как их выдергивать и преподносить пользователю.
Это-наш план реализации. Давайте теперь разбираться по пунктам, что и как надо сделать. Прежде всего подсчет. Понятно что напрямую файл отдавать нельзя прежде чем его отдать надо прибавить к счетчику +1. Значит это реализуем примерно вот так:


<?php

//код файла req.php

define('URL_DIR','http://phpbegun.ru/files_dir/');

define('ABS_DIR',$_SERVER['DOCUMENT_ROOT']);

//Определяем нужные нам константы

$namefile htmlspecialchars(str_replace("/","",$_GET['name'])); 

//Через гет передаем параметр-имя

if(!$namefile

{

    echo 
'Произошла ошибка! Файл с таким именем не найден.';

}

$array = array(); //массив данных

if(file_exists(ABS_DIR.'/schet.txt'))

{

    
$array unserialize(file_get_contents(ABS_DIR.'/schet.txt'));

    
//Файл который будет содержать данные о кол-ве скачиваний

    //в виде сериализованного массива

    
if(!$array[$namefile]) $array[$namefile] = 0;

    
$schet $array[$namefile]+1;

    
//$array[$namefile] содержит кол-во скачиванй этого файла

}

else 

{

    
$schet 1;

}

$array[$namefile] = $schet;

//присваиваем новое значение элементу массива

$array serialize($array);

//сериализуем данные

@file_put_contents(ABS_DIR.'/schet.txt',$array);

//пишем в файл причем не проверяем 

//записалось или нет ибо скачивание 

//должно начаться независимо от этого 

header("Location: ".URL_DIR."$namefile");

//Переадресуем запрос на скачиваемый файл

?>

Итак первая часть кода есть. Данный скрипт должен выполняться перед началом скачивания файла, т.е. на него должны вести все ссылки с вашего сайта для скачивания. Этот сценарий подразумевает что права на корневой дирректории и на самом файле будут таковы чтобы была возможна запись (cmod 0777). Так же хочу заметить, что для больших файлохранилищ даный алгоритм не лучшее решение и гораздо правильнее было бы использовать MySQL. Но для тех у кого небольшой сайт с малым количеством файлов это наиболее оптимальный вариант. Фактически мы решили задачи 1 и 2. Храним данныее в файле в сериализованном виде (настоятельно рекомендую почитать о функциях serialize и unserialize в официальном мануале, очень полезная штука). Кроме того сначала подсчитываем количество скачиваний, увеличиваем его, сохраняем в файл и потом выводим. как же теперь преподносить данные пользователю? При формировании страницы надо лишь считывать массив данных, и выдергивать с именем данного файла нужное нам число. Примерно вот так:


<?php

define
('URL_DIR','http://phpbegun.ru/files_dir/');

define('ABS_DIR',$_SERVER['DOCUMENT_ROOT']);

$data unserialize(file_get_contents(ABS_DIR.'/schet.txt'));

echo 
'Вот тут можно скачать файл '.

'<a href="/files_dir/req.php?name=name.txt">Names(',$data['name.txt'],')</a>';

?>

Простейший счетчик скачиваний файлов готов. Советую вам все define вынести в отдельный файл, чтобы не определять их и в файле скачивания и в файле вывода, и подключать через require_once. На этом пожалуй закончу данную статью, ибо пищу для размышлений я вам дал, а что-то более интересное и элегантное вы сможете конечно же написать и сами если постараетесь. Надеюсь, что вы поделитесь своими вариантами решений, будет интересно посмотреть.
Удачи в обучении :)

Комментарии (10) к “Количество скачиваний файла на PHP”

  • Kreatiff:

    Полезная статью! Реализовал на своём сайте с минимальными изменениями – работает ! Была проблема, когда на хостинг залил, пришлось добавить
    .’/’ в

    define(‘ABS_DIR’,$_SERVER['DOCUMENT_ROOT'].’/');

    слэша нехватало ему…:) Не знаю может я «протупил» – но так оно работает, по-другому- нет !
    Спасибо Автору.
    Подскажи, при каких «минимальных» правах инфа будет сохраняться в файле schet.txt ?? Я поставил 777 – это не много ??

  • простите, но Ваш скрипт не избавляет от коллизий, например одновременно файл лезут скачивать несколько человек, например первый, получит массив когда он еще не будет перезаписан остальными, а запишет его послденим, тем самым переписав его значение, удалив записанные в этот момент. тут нужно или использовать lock или создание врменного файла, так как Lock не сработает на Windows

  • При написании данного поста я не преследовал цели написать полностью готовый к употреблению скрипт, иначе наффиг тогда учиться если кто-то может написать за вас? тем более гораздо удобнее все это делать с базой, а не на файликах. Да здесь конечно нужно использовать блокировку файла (flock) во время записи. Но цель моя не в том чтобы сделать готовое решение, а в том чтобы задать направление тем кто учится, чтобы у них у самих был простор для размышлений, изменений, чтобы человеку хотелось и дальше обучаться и сделать идеально рабочую версию.

  • 0777 – это слишком много, в таком случае надо дополнительно закрыть доступ из веба хотя бы

    Странно вы пишете комментарии в коде – после блока.

  • Зачем?) ну увидит человек количество скачиваний? Это же не сверх важные данные которые надо прятать.

  • По моему мнению, посторонний человек не должен видеть данных о сайте, если это специально не предусмотрено.

  • эти данные все равно выводятся пользователю) какая разница?) если так желаете можно их скрыть но в данном случае на мой взгляд-это непринципиально

  • Павел:

    Ребята, это же бред. Файлами лучше не делать – делайте СРАЗУ, все на базе. Поверьте мне – лучше сейчас нормально выучить MySQL или подобные на нужном уровне, чем потом пыхтеть, переписывая такой говнокод.
    ЗЫ
    mysql_query(«UPDATE count_down SET count=count+1 WHERE id = $id»);
    – это увеличение счетчика файла по ID. Ну проще же, не правда ли?
    а вот так можно ужнать кол-во скаживаний:
    $res = mysql_fetch_row(mysql_query(«SELECT count FROM count_down WHERE id=$id»));
    echo(«Скачиваний: {$res[0]}»);

    ВСЕ!
    ЗЫЗЫ: Мимо проходил

  • Вы просто не работали с большими проектами)

Оставить Ответ