Создаем счетчик загрузок файла с помощью PHP и MySQL. Устанавливаем счетчик скачиваний — обзор плагинов для Вордпресс Счетчик скачивания файлов php


Давно уже не было уроков про PHP и MySQL. Сегодня мы создадим простой, но эффективный счетчик скачиваний.

У каждого файла будет запись в ряду таблицы базы данных. В этой же таблице будет сохраняться количество скачиваний файла. PHP будет обновлять БД MySQL и перенаправлять пользователя на необходимый файл.

Для отслеживания количества скачиваний любого файла, Вам необходимо его положить в папку files и использовать специальный УРЛ для обращения к нему.

Шаг 1 - XHTML

Первым шаг - это создание разметки нашего скрипта. Она очень простая - у нас есть div file-manager, который содержит неупорядоченный список, в котором каждый элемент списка отвечает за файл.

Файлы, скачивания которых необходимо отследить, помещены в папку files в корневой папке скрипта. PHP потом проходит по всем файлам и добавляет каждый в качестве элемента списка (li) в неупорядоченный список.

demo.php


  • photoShoot-1.0.zip 0 download

Обратите внимание, что атрибут href ссылок передает название файла в качестве параметра для download.php. именно здесь и происходит отслеживание количества скачиваний.

Вам необязательно отображать все таким же образом - Вы просто можете давать ссылки на download.php на Ваших страницах и все скачивания не пройдут мимо.

Шаг 2 - CSS

После разметки давайте займемся оформлением. CSS правила ниже обращаются к div file-manager с помощью id (символ #), так как он встречается только 1 раз на странице, и к остальным элементам по названиям классов.

styles.css

#file-manager{ background-color:#EEE; border:1px solid #DDD; margin:50px auto; padding:10px; width:400px; }
ul.manager li{ background:url("img/bg_gradient.gif") repeat-x center bottom #F5F5F5; border:1px solid #DDD; border-top-color:#FFF; list-style:none; position:relative; } ul.manager li a{ display:block; padding:8px; } ul.manager li a:hover .download-label{ /* При наведении на мпимок, показать зеленый текст скачать: */ display:block; } span.download-label{ background-color:#64B126; border:1px solid #4E9416; color:white; display:none; font-size:10px; padding:2px 4px; position:absolute; right:8px; text-decoration:none; text-shadow:0 0 1px #315D0D; top:6px; /* CSS3 Закругленные углы */
-moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; } span.download-count{ color:#999; font-size:10px; padding:3px 5px; position:absolute; text-decoration:none; }

Шаг 3 - PHP

Как я говорил раньше, PHP ищет файлы в папке files и выводит каждый файл в качестве элемента списка в неупорядоченном списке. Давайте взглянем на то, как это происходит

demo.php - верхняя часть

// Соо бщение об ошибках : error_reporting(E_ALL^E_NOTICE); // : require "connect.php"; $extension=""; $files_array = array(); /* Открываем папку и проходим по всем файлам : */ $dir_handle = @opendir($directory) or die("There is an error with your file directory!"); while ($file = readdir($dir_handle)) { /* Пропускаем системные файлы : */ if($file{0}==".") continue; /* end() выводит последний элемент массива сгенерированного функцией explode(): */ $extension = strtolower(end(explode(".",$file))); /* Пропускаем php файлы : */ if($extension == "php") continue; $files_array=$file; } /* Сортируем файлы в алфавитном порядке */ sort($files_array,SORT_STRING); $file_downloads=array(); $result = mysql_query("SELECT * FROM download_manager"); if(mysql_num_rows($result)) while($row=mysql_fetch_assoc($result)) { /* Ключ массива $file_downloads будет названием файла , и будет содержать кол-во скачиваний : */ $file_downloads[$row["filename"]]=$row["downloads"]; }

Обратите внимание как мы выбираем все ряды с таблицы download_manager с помощью mysql_query(), и позже добавляем их к массиву $file_downloads с названием файла в качестве ключа к количеству скачиваний. Таким образом, далее в коде, мы можем писать $file_downloads["archive.zip"] и выводить количество скачиваний.

Ниже Вы видите код, который генерирует элементы списка:

demo.php - средняя часть

Foreach($files_array as $key=>$val) { echo "

  • ".$val." ".(int)$file_downloads[$val]." download
  • "; }

    Все делается просто с помощью цикла foreach массива $files_array. После этого все выводится с помощью echo.

    Теперь давайте более детально взглянем на то, как происходит отслеживание файлов.

    download.php

    // Проверка ошибок : error_reporting(E_ALL^E_NOTICE); // Включаем файл подключения к ДБ : require("connect.php"); if(!$_GET["file"]) error("Missing parameter!"); if($_GET["file"]{0}==".") error("Wrong file!"); if(file_exists($directory."/".$_GET["file"])) { /* Есл и посетитель не поисковой бот , засчитываем скачивание : */ if(!is_bot()) mysql_query(" INSERT INTO download_manager SET filename="".mysql_real_escape_string($_GET["file"])."" ON DUPLICATE KEY UPDATE downloads=downloads+1"); header("Location: ".$directory."/".$_GET["file"]); exit; } else error("This file does not exist!"); /* функции помощники : */ function error($str) { die($str); } 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; // Not a bot }

    Важно проверить является ли Ваш посетитель человек или роботом поисковиков. Роботы это конечно хорошо, но не позволим им искажать нашу статистику. Именно поэтому ряд в базе данных обновляется только после проверки is_bot().

    Шаг 4 - MySQL

    Как мы заметили в прошлом шаге, количество скачиваний сохраняется в качестве ряда в таблице download_manager. Для начала давайте объясним как работает этот запрос:

    download.php

    INSERT INTO download_manager SET filename="filename.doc" ON DUPLICATE KEY UPDATE downloads=downloads+1

    Он говорит MySQL вставить новый ряд в таблицу download_manager, и установить поле ряда filename на значение вызванного к скачиванию файла. Однако, поле filename обозначенного как уникальный индекс в таблице. Это означает, что каждый ряд можно вставлять только раз, иначе возникнет ошибка duplicate key error.

    Именно здесь и будет работать вторая часть запроса - ON DUPLICATE KEY UPDATE сообщит MySQL добавить единицу к колонке скачиваний, если файл уже существует в базе.

    Таким образом новые файлы будут автоматически добавляться в БД при первом скачивании.

    Шаг 5 - jQuery

    Для того, чтобы сделать отслеживание в виде реального времени, было бы хорошо обновлять счетчик возле названия файла после каждой загрузки.

    Мы это сделаем с помощью jQuery:

    script.js

    $(document).ready(function(){ /* Код выполняется после загрузки страницы */ $("ul.manager a").click(function(){ var countSpan = $(".download-count",this); countSpan.text(parseInt(countSpan.text())+1); }); });

    Мы просто присваиваем обработчик кликов к ссылкам, который ведут к файлам, и при каждом нажатии мы добавляем значение.

    Шаг 6 - htaccess

    Есть еще одна вещь, которую необходимо сделать. Download.php редиректит пользователя к запрашиваемому файлу, который был передан в качестве параметра. Однако, Вы могли заметить, что некоторые типы файлов браузеры пытаются открыть напрямую. Нам же необходимо инициировать их загрузку. Это можно сделать с помощью нескольких строк внутри файла.htacess, который находится в папке files.

    ForceType application/octet-stream

    Вот теперь наш счетчик полностью готов!

    Заключение

    Для того, чтобы демо заработало у Вас необходимо воссоздать таблицу download_manager в базе данных MySQL. Вы можете найти необходимый SQL код в исходниках.

    После этого, добавьте Ваши данные для соединения с БД в файле configuration.php.

    В сегодняшней статье, мы создадим простую, но надежную систему учета загрузок файлов. Каждый файл будет иметь соответствующую строку в базе данных, где будет хранится общее число загрузок этого файла. PHP будет обновлять базу данных MySQL, и перенаправлять пользователей на соответствующие файлы.

    Чтобы отслеживать количество загрузок, вам понадобится только загрузить файлы в нужную папку, и использовать определенный URL для доступа к ним.

    Шаг 1 – XHTML

    Для начала нам понадобится XHTML-разметка. Она очень простая – это общий блок file-manager , содержащий маркированный список, в котором ссылка на каждый файл будет находится внутри элемента li .

    Файлы, по которым будет учитываться количество скачиваний, нужно загрузить в папку files , расположенную в корневой директории скрипта (вы можете посмотреть как организована структура файлов, в архиве с приведенным примером). PHP будет проходить циклом по всем файлам в папке, и добавлять каждый файл в виде отдельного элемента li, в маркированный список.

    demo.php

    • photoShoot-1.0.zip 0 download

    Обратите внимание, что атрибут href у ссылки передает имя загружаемого файла в качестве параметра для файла download.php . Именно здесь будет происходить подсчет загрузок, как вы увидите в дальнейшем.

    Вам не обязательно пользоваться именно этим интерфейсом для организации подсчета загрузок. Вы можете просто разместить ссылки на download.php на страницах блога или сайта, и все загрузки будут подсчитаны правильно.

    Шаг 2 – CSS

    После того как наша XHTML-разметка готова, мы можем сконцентрироваться на внешнем виде нашего скрипта. CSS-стили, представленные ниже, назначают внешний вид блоку file-manager, через его ID, поскольку он у нас один на странице. Остальные элементы стилизуются через имена классов.

    style.css

    #file-manager{ background-color:#EEE; border:1px solid #DDD; margin:50px auto; padding:10px; width:400px; } ul.manager li{ background:url("img/bg_gradient.gif") repeat-x center bottom #F5F5F5; border:1px solid #DDD; border-top-color:#FFF; list-style:none; position:relative; } ul.manager li a{ display:block; padding:8px; } ul.manager li a:hover .download-label{ /* When a list is hovered over, show the download green text inside it: */ display:block; } span.download-label{ background-color:#64B126; border:1px solid #4E9416; color:white; display:none; font-size:10px; padding:2px 4px; position:absolute; right:8px; text-decoration:none; text-shadow:0 0 1px #315D0D; top:6px; /* CSS3 Rounded Corners */ -moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; } span.download-count{ color:#999; font-size:10px; padding:3px 5px; position:absolute; text-decoration:none; }

    Обратите внимание, что здесь подпись “download” скрыта по умолчанию, с помощью свойства display: none . Она отображается через display:block , только при наведении мыши на ссылку, без использования JavaScript. Немного CSS3 используется для закругления уголков у подписи.

    Шаг 3 – PHP

    Как мы уже говорили выше, PHP проходит циклом по всей папке files , и выводит каждый файл в виде элемента li маркированного списка. Давайте рассмотрим подробнее, как это происходит.

    demo.php — Верхняя часть

    // Error reporting: error_reporting(E_ALL^E_NOTICE); // Including the DB connection file: require "connect.php"; $extension=""; $files_array = array(); /* Opening the thumbnail directory and looping through all the thumbs: */ $dir_handle = @opendir($directory) or die("There is an error with your file directory!"); while ($file = readdir($dir_handle)) { /* Skipping the system files: */ if($file{0}==".") continue; /* end() returns the last element of the array generated by the explode() function: */ $extension = strtolower(end(explode(".",$file))); /* Skipping the php files: */ if($extension == "php") continue; $files_array=$file; } /* Sorting the files alphabetically */ sort($files_array,SORT_STRING); $file_downloads=array(); $result = mysql_query("SELECT * FROM download_manager"); if(mysql_num_rows($result)) while($row=mysql_fetch_assoc($result)) { /* The key of the $file_downloads array will be the name of the file, and will contain the number of downloads: */ $file_downloads[$row["filename"]]=$row["downloads"]; }

    Обратите внимание, как мы выбираем все записи из таблицы download_manager с помощью mysql_query() и затем добавляем их в массив $file_downloads , с ключом массива filename, и значением downloads. Таким образом, далее в коде, мы сможем записать $file_downloads[‘archive.zip’] , и вывести количество загрузок этого файла.

    Ниже представлен код, который используется для генерации элементов li маркированного списка.

    demo.php – Центральная часть

    Foreach($files_array as $key=>$val) { echo "

  • ".$val." ".(int)$file_downloads[$val]." download
  • "; }

    Все очень просто – проходим циклом foreach по массиву $files_array , и выводим на страницу нужные данные в соответствующей разметке.

    Теперь давайте более подробно рассмотрим как происходит учет загрузок.

    download.php

    // Error reporting: error_reporting(E_ALL^E_NOTICE); // Including the connection file: require("connect.php"); if(!$_GET["file"]) error("Missing parameter!"); if($_GET["file"]{0}==".") error("Wrong file!"); if(file_exists($directory."/".$_GET["file"])) { /* If the visitor is not a search engine, count the downoad: */ if(!is_bot()) mysql_query(" INSERT INTO download_manager SET filename="".mysql_real_escape_string($_GET["file"])."" ON DUPLICATE KEY UPDATE downloads=downloads+1"); header("Location: ".$directory."/".$_GET["file"]); exit; } else error("This file does not exist!"); /* Helper functions: */ function error($str) { die($str); } function is_bot() { /* This function will check whether the visitor is a search engine robot */ $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; // Not a bot }

    Здесь обязательно нужно проверить, не является ли посетитель роботом поисковой системы, сканирующим ваши ссылки. Роботы – это хорошие посетители, поскольку они помогают включить ваш сайт в поисковые сервисы, однако в нашем случае, они могут исказить статистику загрузок. Вот почему база данных обновляется только после того, как посетитель пройдет проверку is_bot().

    Шаг 4 – MySQL

    Как мы упоминали в предыдущем шаге, количество загрузок записывается в виде строки, в таблицу download_manager, базы данных MySQL. Сначала, позвольте объяснить как работает эта часть запроса:

    download.php

    INSERT INTO download_manager SET filename="filename.doc" ON DUPLICATE KEY UPDATE downloads=downloads+1

    Первая часть запроса говорит MySQL вставить новую строчку в таблицу download_manager , и установить значение поля filename равным имени запрашиваемого для загрузки файла. Кроме этого, поле filename определено как уникальный индекс таблицы. Это значит, что строка с конкретным именем файла, может быть вставлена только один раз, иначе произойдет ошибка дублирования ключевых полей.

    Именно в этом случае, вступает в силу вторая часть запроса — ON DUPLICATE KEY UPDATE , которая увеличивает значение поля downloads на единицу, если этот файл уже записан в базе данных.

    Таким образом, новые файлы будут автоматически вставляться в базу данных в первый раз, после того как загружены.

    Шаг 5 – jQuery

    Для того, чтобы сделать наш счетчик загрузок более наглядным, было бы неплохо добавить возможность обновлять счетчик, находящийся рядом с именем файла, сразу после того, как пользователь начнет загрузку. Пока что, для того чтобы увидеть новые значения счетчиков, пользователю нужно перезагрузить страницу.

    Это можно исправить небольшим фрагментом кода:

    script.js

    $(document).ready(function(){ /* This code is executed after the DOM has been completely loaded */ $("ul.manager a").click(function(){ var countSpan = $(".download-count",this); countSpan.text(parseInt(countSpan.text())+1); }); });

    Мы просто назначили обработчик события на клик по ссылке. Каждый раз, после того, как пользователь кликнет по ссылке, мы увеличиваем текущее значение загрузок на единицу.

    Шаг 6 – htaccess

    Нам осталось сделать еще одну вещь, прежде чем можно будет назвать работу законченной. Возможно, вы уже заметили, что некоторые типы файлов, браузер по умолчанию пытается сразу же открывать. Вместо этого, нам нужно запускать загрузку файла. Это довольно легко сделать, добавив несколько строчек внутри файла .htaccess , расположенного в папке files :

    ForceType application/octet-stream

    Вот и все, наш счетчик загрузок готов.

    Заключение

    Чтобы запустить этот пример на своем собственном сервере, вам понадобится создать таблицу download_manager в базе данных MySQL, к которой у вас разумеется есть доступ. В архиве с примером, есть файл table.sql , который содержит необходимый SQL-код, который создаст нужную таблицу.

    После этого, просто укажите свои данные подключения к базе, в файле configuration.php .

    На многих сайтах можно увидеть ссылки на загрузку файлов. Например, фирмы-производители на своих официальных страницах размещают инструкции к тому или иному товару. Кроме того, разработчики программного обеспечения тоже предлагают бесплатно загрузить свою программу, давая пользователю таким образом ознакомится с ее функциями и работой.

    Выставляя для свободной загрузки тот или иной файл, важно знать, сколько раз он был загружен. Это необходимо, в первую очередь, для статистики, анализ которой поможет определить полезность информации для конечного пользователя.

    Как на сайте WordPress установить счетчик скачиваний?

    Среди инструментов WordPress нет каких-либо возможностей увидеть эту статистику. Поэтому будем использовать стороннее решение – плагин Kama Click Counter .

    Плагин Kama Click Counter

    Бесплатный плагин Kama Click Counter предоставляет все необходимые средства для точного подсчета количества загрузок того или иного файла. Итак, во-первых, его нужно установить и активировать. Для примера выведем на странице записи ссылку на pdf -файл, для которого и будем считать количество скачиваний. Следует отметить, что файлы на сайт загружаются стандартными способами Медиабиблиотеки WordPress (Медиафайлы -> Добавить новый ). Дальше необходимо открыть на редактирование запись или страницу. В контентной части нужно поставить курсор в то место, где будет размещена ссылка на файл, и нажать появившеюся кнопку в панели инструментов визуального редактора.

    Во всплывающем окне плагин попросит Вас выбрать загруженный ранее файл. Для этого нужно нажать кнопку с иконкой лупы.

    В библиотеке медиафайлов следует выбрать нужный файл и нажать кнопку Выбрать файл .

    В итоге в контентную часть записи или страницы будет вставлен специальный шорткод, который и служит для отображения ссылки для загрузки файла.

    После обновления материала (кнопка Обновить ) можно переходить на сайт для его просмотра.

    Плагин также способен показать статистику загрузок и в пользовательской части сайта – в виджете. Отметим, что плагин по умолчанию не показывает в виджете конкретные цифры, что и сколько раз было скачано. Выводится лишь список наиболее часто загружаемых файлов. Для этого следует перейти в админ-раздел Внешний вид -> Виджеты и перетащить виджет КСС:Топ Загрузок в желаемое место сайдбара.

    Видно, что в виджете доступно несколько опций, позволяющих видоизменить список.

    Тут можно задать следующие основные параметры:

    • заголовок виджета (поле Заголовок );
    • количество выводимых файлов в списке (сколько ссылок показывать? );
    • сортировка результатов (как сортировать результат? );
    • настройка внешнего вида шаблона (блоки Шаблон и CSS шаблона ).

    Особенностью плагина является гибкая настройка шаблона. Тут можно использовать так называемые теги, на месте которых будет отображена та или иная информация.

    После того, как все настройки виджета были выполнены и сохранены (кнопка Сохранить ), можно смотреть результат на сайте.

    // Удаляем преобразование режима "магических кавычек" $_POST["content"] = addslashes($_POST["content"]);

    // Перезаписываем содержимое файла file_put_contents($_POST["filename"], "$_POST");

    4.9. Счетчик загрузок файлов

    Работа всех счетчиков загрузок файлов основана на том, что посетителю в качестве ссылки для загрузки предоставляется не сам файл, а ссылка на скрипт, который учитывает загрузку и отправляет файл браузеру пользователя.

    Будем строить наш счетчик таким образом, чтобы ссылки на загрузку файла представляли собой ссылки на текущую страницу с передачей в качестве параметра имени файла, например, index.php?down=archive.zip . Скрипт будет проверять, передан ли параметр down , и если это так, то будет регистрировать загрузку архива в файле filecount.txt. При повторной загрузке страницы из файла будут извлекаться значения счетчиков для каждого из архивов для вывода в окно браузера. Передача файла на загрузку будет осуществляться отсылкой посетителю HTTP-заголовка Location с указанием пути к загружаемому архиву. Скрипт счетчика загрузок файлов может выглядеть так, как это представлено в листинге 4.31.

    Листинг 4.31. Счетчик загрузок файлов

    // Выставляем уровень обработки ошибок error_reporting(E_ALL & ~E_NOTICE);

    // Регистрируем имена файлов в массиве

    $file_name = array("archive1.zip","archive2.zip","archive3.zip");

    // Имя файла, где хранится статистика $countname = "filecount.txt";

    // Если файл существует,

    // считываем текущую статистику в массив if(file_exists($countname))

    // Получаем содержимое счетчика

    $content = file_get_contents($countname);

    // Распаковываем массив

    $count = unserialize($content);

    // Если такого файла нет - создаем его,

    // а статистику обнуляем

    // Заполняем массив $count нулевыми значениями foreach($file_name as $file)

    $count[$file] = 0;

    // Упаковываем массив и помещаем его в счетчик file_put_contents($countname, serialize($count));

    // Проверяем, не передано ли значение параметра down

    // через метод GET

    if(isset($_GET["down"]))

    // Проверяем, входит ли значение параметра $_GET["down"]

    // в массив $file_name

    if(in_array($_GET["down"],$file_name))

    // Регистрируем факт загрузки данного файла

    // Увеличиваем значение счетчика с ключом

    // $_GET["down"] на единицу

    $count[$_GET["down"]]++;

    // Перезаписываем файл счетчика file_put_contents($countname, serialize($count));

    echo "Файл $file был загружен ".intval($count[$file])." раз
    ";

    Имена загружаемых файлов хранятся в массиве $file_name , добавление нового архива приводит к автоматическому его учету в системе. Предварительная регистрация в массиве необходима по нескольким причинам. Во-первых, принимая имя массива через параметр down , необходимо проверить, входит ли он в число файлов, разрешенных к загрузке. Во-вторых, обрабатывать имена файлов в массиве гораздо удобнее. Так массив $count , в котором хранится количество загрузок файлов, автоматически строится на основании массива зарегистрированных в системе файлов,

    массив удобно упаковывать при помощи функции serialize() в строку, а затем распаковывать обратно в массив при помощи функции unserialize() .

    З АМЕЧАНИЕ

    Важно помнить, что отправка всех HTTP-заголовков должна осуществляться до отправки основного содержимого, иначе их отправка будет невозможна и интерпретатор PHP выдаст предупреждение "Warning: Cannot modify header information - headers already sent by"

    (Предупреждение: невозможно модифицировать заголовочную информацию - заголовки уже отправлены). Это диктуется протоколом HTTP: сначала отправляются заголовки, затем содержимое документа, поэтому любой вывод в окно браузера воспринимается как окончание отправки заголовков и начало отправки тела документа. Если вывод в окно браузера до отправки заголовков неизбежен, необходимо прибегать к функциям управления выводом, помещая весь вывод в буфер и отправляя его в конце работы скрипта.

    Как видно из листинга 4.31, в скрипте обрабатывается ситуация первого запуска, когда отсутствует файл filecount.txt - он автоматически создается при первой загрузке страницы, инициированный нулевыми значениями для каждого файла из массива $file_name . Результат работы скрипта из листинга 4.31 можно видеть на рис. 4.4.

    Рис. 4.4. Результат работы счетчика файлов

    4.10. Сохранение текстовых и графических файлов

    Переход по ссылке на текстовые файлы или файлы HTML приводит к отображению их в окне браузера, что не всегда удобно, особенно, если файл предназначен для загрузки. Та же участь ожидает графические файлы и вообще любые файлы, которые браузер может отобразить. О содержимом файла браузер посетителя "узнает" от сервера, т. к. каждый файл сопровождается HTTP-заголовками, сообщающими клиенту о содержимом, размере загружаемого файла, необходимости установить cookie и т. п. Если тип файла не удалось определить, он отправляется просто как двоичный поток.

    Подавить такое поведение можно, отправив HTTP-заголовки, представленные в листинге 4.32.

    Листинг 4.32. Скрипт, позволяющий сохранять текстовые и графические файлы

    $filename = basename($_GET["down"]); header("Content-Disposition: attachment; filename=$filename"); header("Content-type: application/octet-stream"); header("Content-length: ".filesize($_GET["down"]));

    echo file_get_contents($_GET["down"]); ?>

    Скрипт в листинге 4.32 принимает в качестве GET-параметра имя файла, например,

    index.php?down=filetext.txt. При помощи функции basename() извлекается имя

    файла (на тот случай, если GET-параметр down содержит путь к файлу). HTTPзаголовок Content-Disposition задает имя сохраняемого файла, которое определяется атрибутом filename . В приведенном скрипте параметр filename совпадает с именем отправляемого файла, однако в качестве параметра filename может быть передано произвольное имя. HTTP-заголовок Content-type сообщает о том, что передаваемые данные являются двоичными, и браузеру их не следует интерпретировать. HTTP-заголовок Content-length передает клиенту размер файла. В последней строке выводится содержимое файла, переданное через параметр $_GET["down"] , которое извлекается при помощи функции file_get_contents() . Результат работы скрипта из листинга 4.32 представлен на рис. 4.5.

    З АМЕЧАНИЕ

    Важно, чтобы после вывода содержимого файла больше ничего не выводилось в поток: ни конструкцией echo , ни непосредственным выводом - иначе все будет прикреплено в конец файла. Это относится и к возможным пробелам, и к переводам строк после завершающего тега ?> .

    Рис. 4.5. Диалоговое окно для загрузки файла

    Давно уже не было уроков про PHP и MySQL. Сегодня мы создадим простой, но эффективный счетчик скачиваний.

    У каждого файла будет запись в ряду таблицы базы данных. В этой же таблице будет сохраняться количество скачиваний файла. PHP будет обновлять БД MySQL и перенаправлять пользователя на необходимый файл.

    Для отслеживания количества скачиваний любого файла, Вам необходимо его положить в папку files и использовать специальный УРЛ для обращения к нему.

    Шаг 1 - XHTML

    Первым шаг - это создание разметки нашего скрипта. Она очень простая - у нас есть div file-manager, который содержит неупорядоченный список, в котором каждый элемент списка отвечает за файл.

    Файлы, скачивания которых необходимо отследить, помещены в папку files в корневой папке скрипта. PHP потом проходит по всем файлам и добавляет каждый в качестве элемента списка (li) в неупорядоченный список.

    demo.php


    • photoShoot-1.0.zip 0 download

    Обратите внимание, что атрибут href ссылок передает название файла в качестве параметра для download.php. именно здесь и происходит отслеживание количества скачиваний.

    Вам необязательно отображать все таким же образом - Вы просто можете давать ссылки на download.php на Ваших страницах и все скачивания не пройдут мимо.

    Шаг 2 - CSS

    После разметки давайте займемся оформлением. CSS правила ниже обращаются к div file-manager с помощью id (символ #), так как он встречается только 1 раз на странице, и к остальным элементам по названиям классов.

    styles.css

    #file-manager{ background-color:#EEE; border:1px solid #DDD; margin:50px auto; padding:10px; width:400px; }
    ul.manager li{ background:url("img/bg_gradient.gif") repeat-x center bottom #F5F5F5; border:1px solid #DDD; border-top-color:#FFF; list-style:none; position:relative; } ul.manager li a{ display:block; padding:8px; } ul.manager li a:hover .download-label{ /* При наведении на мпимок, показать зеленый текст скачать: */ display:block; } span.download-label{ background-color:#64B126; border:1px solid #4E9416; color:white; display:none; font-size:10px; padding:2px 4px; position:absolute; right:8px; text-decoration:none; text-shadow:0 0 1px #315D0D; top:6px; /* CSS3 Закругленные углы */
    -moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; } span.download-count{ color:#999; font-size:10px; padding:3px 5px; position:absolute; text-decoration:none; }

    Шаг 3 - PHP

    Как я говорил раньше, PHP ищет файлы в папке files и выводит каждый файл в качестве элемента списка в неупорядоченном списке. Давайте взглянем на то, как это происходит

    demo.php - верхняя часть

    // Соо бщение об ошибках : error_reporting(E_ALL^E_NOTICE); // : require "connect.php"; $extension=""; $files_array = array(); /* Открываем папку и проходим по всем файлам : */ $dir_handle = @opendir($directory) or die("There is an error with your file directory!"); while ($file = readdir($dir_handle)) { /* Пропускаем системные файлы : */ if($file{0}==".") continue; /* end() выводит последний элемент массива сгенерированного функцией explode(): */ $extension = strtolower(end(explode(".",$file))); /* Пропускаем php файлы : */ if($extension == "php") continue; $files_array=$file; } /* Сортируем файлы в алфавитном порядке */ sort($files_array,SORT_STRING); $file_downloads=array(); $result = mysql_query("SELECT * FROM download_manager"); if(mysql_num_rows($result)) while($row=mysql_fetch_assoc($result)) { /* Ключ массива $file_downloads будет названием файла , и будет содержать кол-во скачиваний : */ $file_downloads[$row["filename"]]=$row["downloads"]; }

    Обратите внимание как мы выбираем все ряды с таблицы download_manager с помощью mysql_query(), и позже добавляем их к массиву $file_downloads с названием файла в качестве ключа к количеству скачиваний. Таким образом, далее в коде, мы можем писать $file_downloads["archive.zip"] и выводить количество скачиваний.

    Ниже Вы видите код, который генерирует элементы списка:

    demo.php - средняя часть

    Foreach($files_array as $key=>$val) { echo "

  • ".$val." ".(int)$file_downloads[$val]." download
  • "; }

    Все делается просто с помощью цикла foreach массива $files_array. После этого все выводится с помощью echo.

    Теперь давайте более детально взглянем на то, как происходит отслеживание файлов.

    download.php

    // Проверка ошибок : error_reporting(E_ALL^E_NOTICE); // Включаем файл подключения к ДБ : require("connect.php"); if(!$_GET["file"]) error("Missing parameter!"); if($_GET["file"]{0}==".") error("Wrong file!"); if(file_exists($directory."/".$_GET["file"])) { /* Есл и посетитель не поисковой бот , засчитываем скачивание : */ if(!is_bot()) mysql_query(" INSERT INTO download_manager SET filename="".mysql_real_escape_string($_GET["file"])."" ON DUPLICATE KEY UPDATE downloads=downloads+1"); header("Location: ".$directory."/".$_GET["file"]); exit; } else error("This file does not exist!"); /* функции помощники : */ function error($str) { die($str); } 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; // Not a bot }

    Важно проверить является ли Ваш посетитель человек или роботом поисковиков. Роботы это конечно хорошо, но не позволим им искажать нашу статистику. Именно поэтому ряд в базе данных обновляется только после проверки is_bot().

    Шаг 4 - MySQL

    Как мы заметили в прошлом шаге, количество скачиваний сохраняется в качестве ряда в таблице download_manager. Для начала давайте объясним как работает этот запрос:

    download.php

    INSERT INTO download_manager SET filename="filename.doc" ON DUPLICATE KEY UPDATE downloads=downloads+1

    Он говорит MySQL вставить новый ряд в таблицу download_manager, и установить поле ряда filename на значение вызванного к скачиванию файла. Однако, поле filename обозначенного как уникальный индекс в таблице. Это означает, что каждый ряд можно вставлять только раз, иначе возникнет ошибка duplicate key error.

    Именно здесь и будет работать вторая часть запроса - ON DUPLICATE KEY UPDATE сообщит MySQL добавить единицу к колонке скачиваний, если файл уже существует в базе.

    Таким образом новые файлы будут автоматически добавляться в БД при первом скачивании.

    Шаг 5 - jQuery

    Для того, чтобы сделать отслеживание в виде реального времени, было бы хорошо обновлять счетчик возле названия файла после каждой загрузки.

    Мы это сделаем с помощью jQuery:

    script.js

    $(document).ready(function(){ /* Код выполняется после загрузки страницы */ $("ul.manager a").click(function(){ var countSpan = $(".download-count",this); countSpan.text(parseInt(countSpan.text())+1); }); });

    Мы просто присваиваем обработчик кликов к ссылкам, который ведут к файлам, и при каждом нажатии мы добавляем значение.

    Шаг 6 - htaccess

    Есть еще одна вещь, которую необходимо сделать. Download.php редиректит пользователя к запрашиваемому файлу, который был передан в качестве параметра. Однако, Вы могли заметить, что некоторые типы файлов браузеры пытаются открыть напрямую. Нам же необходимо инициировать их загрузку. Это можно сделать с помощью нескольких строк внутри файла.htacess, который находится в папке files.

    ForceType application/octet-stream

    Вот теперь наш счетчик полностью готов!

    Заключение

    Для того, чтобы демо заработало у Вас необходимо воссоздать таблицу download_manager в базе данных MySQL. Вы можете найти необходимый SQL код в исходниках.

    После этого, добавьте Ваши данные для соединения с БД в файле configuration.php.