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

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

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

Игорь Гергель

Единственный обладатель значков золотой WordPress и бронзовый WooCommerce на StackOverflow RU. WordPress Core contributor. Работал ведущим девелопером в команде WPML.

%d такие блоггеры, как: