Часто возникает вопрос — как посчитать число скачиваний файла и спрятать реальную ссылку на скачиваемый файл?
Для решения этой задачи надо сделать две вещи: перехватить клик на ссылку и отдать реальный файл пользователю средствами php.
Что происходит при клике на фиктивную ссылку, указывающую на несуществующую страницу сайта? WordPress инициализирует ядро и пытается выдать страницу 404. В этот момент надо вмешаться своей функцией, обновить счётчик загрузок и отдать реальный файл. Ниже код такой функции.
/** * Rewrite download link by its url. * Increase download count. */ public function rewrite_download_link() { /** @var wpdb $wpdb */ global $wpdb; $uri = $_SERVER['REQUEST_URI']; $path = wp_parse_url( $uri, PHP_URL_PATH ); if ( 0 === strpos( trailingslashit( $path ), self::$link_base ) ) { $download_link = untrailingslashit( $path ); $url = self::get_url( $download_link ); if ( $url ) { $count = self::get_count( $url ); $data = array( 'count' => ++ $count, ); $where = array( 'url' => $url, ); $wpdb->update( self::$table, $data, $where ); self::download_file( $url ); } } }
Функция rewrite_download_link()
срабатывает на событии init
, и проверяет, не начинается ли url с $link_base
. Например, это может быть /downloads/
. Любая ссылка вида http://site.org/downloads/cool.jpg
считается фиктивной и подлежит обработке, в которой обновляется счётчик загрузок, вычисляется реальный url файла и вызывается функция отдачи реального файла пользователю.
Код этой функции приведён ниже.
/** * Download file. * * @param string $url file url. */ private static function download_file( $url ) { if ( ! $url ) { return; } $file_path = ABSPATH . wp_make_link_relative( $url ); $file_name = pathinfo( $file_path, PATHINFO_FILENAME ); $file_extension = pathinfo( $file_path, PATHINFO_EXTENSION ); switch ( $file_extension ) { case 'png': $content_type = 'image/png'; break; case 'gif': $content_type = 'image/gif'; break; case 'tiff': $content_type = 'image/tiff'; break; case 'jpeg': case 'jpg': $content_type = 'image/jpg'; break; default: $content_type = 'application/force-download'; } header( 'Expires: 0' ); header( 'Cache-Control: no-cache, no-store, must-revalidate' ); header( 'Cache-Control: pre-check=0, post-check=0, max-age=0', false ); header( 'Pragma: no-cache' ); header( "Content-type: {$content_type}" ); header( "Content-Disposition:attachment; filename={$file_name}.{$file_extension}" ); header( 'Content-Type: application/force-download' ); // @codingStandardsIgnoreLine readfile( "{$file_path}" ); exit(); }
Функция download_file()
делает полученную ссылку на файл относительной и вычисляет путь к файлу, а потом отдаёт его средствами php. Таким образом, пользователь не имеет возможности узнать, где находится реальный файл и скачать его напрямую.
Полный код класса, который содержит приведённые выше методы, можно найти на нашем GitHub.
Источник: KAGG Design