Как сделать счётчик загрузок и скрыть ссылку на файл

Пример кода реализации счётчика загрузок для скрытых ссылок.

Как сделать счётчик загрузок и скрыть ссылку на файл


Часто возникает вопрос — как посчитать число скачиваний файла и спрятать реальную ссылку на скачиваемый файл?

Для решения этой задачи надо сделать две вещи: перехватить клик на ссылку и отдать реальный файл пользователю средствами 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.

 

Оставьте комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.