core-bundle/src/Resources/contao/library/Contao/Controller.php
public static function sendFileToBrowser($strFile, $inline=false)
	{
		// Make sure there are no attempts to hack the file system
		if (preg_match('@^\.+@', $strFile) || preg_match('@\.+/@', $strFile) || preg_match('@(://)+@', $strFile))
		{
			throw new PageNotFoundException('Invalid file name');
		}

		// Limit downloads to the files directory
		if (!preg_match('@^' . preg_quote(Config::get('uploadPath'), '@') . '@i', $strFile))
		{
			throw new PageNotFoundException('Invalid path');
		}

		$rootDir = System::getContainer()->getParameter('kernel.project_dir');

		// Check whether the file exists
		if (!file_exists($rootDir . '/' . $strFile))
		{
			throw new PageNotFoundException('File not found');
		}

		$objFile = new File($strFile);
		$arrAllowedTypes = StringUtil::trimsplit(',', strtolower(Config::get('allowedDownload')));

		// Check whether the file type is allowed to be downloaded
		if (!\in_array($objFile->extension, $arrAllowedTypes))
		{
			throw new AccessDeniedException(sprintf('File type "%s" is not allowed', $objFile->extension));
		}

		// HOOK: post download callback
		if (isset($GLOBALS['TL_HOOKS']['postDownload']) && \is_array($GLOBALS['TL_HOOKS']['postDownload']))
		{
			foreach ($GLOBALS['TL_HOOKS']['postDownload'] as $callback)
			{
				static::importStatic($callback[0])->{$callback[1]}($strFile);
			}
		}

		// Send the file (will stop the script execution)
		$objFile->sendToBrowser('', $inline);
	}
public static function sendFileToBrowser($strFile, $inline=false)
	{
		// Make sure there are no attempts to hack the file system
		if (preg_match('@^\.+@', $strFile) || preg_match('@\.+/@', $strFile) || preg_match('@(://)+@', $strFile))
		{
			throw new PageNotFoundException('Invalid file name');
		}

		// Limit downloads to the files directory
		if (!preg_match('@^' . preg_quote(Config::get('uploadPath'), '@') . '@i', $strFile))
		{
			throw new PageNotFoundException('Invalid path');
		}

		$rootDir = System::getContainer()->getParameter('kernel.project_dir');

		// Check whether the file exists
		if (!file_exists($rootDir . '/' . $strFile))
		{
			throw new PageNotFoundException('File not found');
		}

		$objFile = new File($strFile);
		$arrAllowedTypes = StringUtil::trimsplit(',', strtolower(Config::get('allowedDownload')));

		// Check whether the file type is allowed to be downloaded
		if (!\in_array($objFile->extension, $arrAllowedTypes))
		{
			throw new AccessDeniedException(sprintf('File type "%s" is not allowed', $objFile->extension));
		}

		// HOOK: post download callback
		if (isset($GLOBALS['TL_HOOKS']['postDownload']) && \is_array($GLOBALS['TL_HOOKS']['postDownload']))
		{
			foreach ($GLOBALS['TL_HOOKS']['postDownload'] as $callback)
			{
				static::importStatic($callback[0])->{$callback[1]}($strFile);
			}
		}

		// Send the file (will stop the script execution)
		$objFile->sendToBrowser('', $inline);
	}
Send a file to the browser so the "save as …" dialogue opens

@param string  $strFile The file path
@param boolean $inline  Show the file in the browser instead of opening the download dialog

@throws AccessDeniedException