• Модуль: main
  • Путь к файлу: ~/bitrix/modules/main/classes/general/file.php
  • Класс: CFile
  • Вызов: CFile::ViewByUser
static function ViewByUser($arFile, $arOptions = array())
{
	$previewManager = new ViewerPreviewManager();
	if ($previewManager->isInternalRequest($arFile, $arOptions))
	{
		$previewManager->processViewByUserRequest($arFile, $arOptions);
	}

	/** @global CMain $APPLICATION */
	global $APPLICATION;

	$fastDownload = (COption::GetOptionString('main', 'bx_fast_download', 'N') == 'Y');

	$attachment_name = "";
	$content_type = "";
	$specialchars = false;
	$force_download = false;
	$cache_time = 10800;
	$fromClouds = false;
	$filename = '';
	$fromTemp = false;

	if(is_array($arOptions))
	{
		if(isset($arOptions["content_type"]))
			$content_type = $arOptions["content_type"];
		if(isset($arOptions["specialchars"]))
			$specialchars = $arOptions["specialchars"];
		if(isset($arOptions["force_download"]))
			$force_download = $arOptions["force_download"];
		if(isset($arOptions["cache_time"]))
			$cache_time = intval($arOptions["cache_time"]);
		if(isset($arOptions["attachment_name"]))
			$attachment_name = $arOptions["attachment_name"];
		if(isset($arOptions["fast_download"]))
			$fastDownload = (bool)$arOptions["fast_download"];
	}

	if($cache_time < 0)
		$cache_time = 0;

	if(is_array($arFile))
	{
		if(isset($arFile["SRC"]))
		{
			$filename = $arFile["SRC"];
		}
		elseif(isset($arFile["tmp_name"]))
		{
			if (mb_strpos($arFile['tmp_name'], $_SERVER['DOCUMENT_ROOT']) === 0)
			{
				$filename = '/'. ltrim(mb_substr($arFile['tmp_name'], mb_strlen($_SERVER['DOCUMENT_ROOT'])), '/');
			}
			elseif (defined('BX_TEMPORARY_FILES_DIRECTORY') && mb_strpos($arFile['tmp_name'], BX_TEMPORARY_FILES_DIRECTORY) === 0)
			{
				$fromTemp = true;
				$tmpPath = COption::GetOptionString('main', 'bx_tmp_download', '/bx_tmp_download/');
				$filename = $tmpPath.ltrim(mb_substr($arFile['tmp_name'], mb_strlen(BX_TEMPORARY_FILES_DIRECTORY)), '/'); //nonexistent path
			}
		}
		else
		{
			$filename = static::GetFileSRC($arFile);
		}
	}
	elseif (($arFile = static::GetFileArray($arFile)))
	{
		$filename = $arFile['SRC'];
	}

	if ($filename == '')
	{
		return false;
	}

	if($content_type == '' && isset($arFile["CONTENT_TYPE"]))
	{
		$content_type = $arFile["CONTENT_TYPE"];
	}

	//we produce resized jpg for original bmp
	if($content_type == '' || $content_type == "image/bmp")
	{
		if(isset($arFile["tmp_name"]))
		{
			$content_type = static::GetContentType($arFile["tmp_name"], true);
		}
		else
		{
			$content_type = static::GetContentType($_SERVER["DOCUMENT_ROOT"].$filename);
		}
	}

	if(isset($arFile["ORIGINAL_NAME"]) && $arFile["ORIGINAL_NAME"] != '')
		$name = $arFile["ORIGINAL_NAME"];
	elseif($arFile["name"] <> '')
		$name = $arFile["name"];
	else
		$name = $arFile["FILE_NAME"];
	if(isset($arFile["EXTENSION_SUFFIX"]) && $arFile["EXTENSION_SUFFIX"] <> '')
		$name = mb_substr($name, 0, -mb_strlen($arFile["EXTENSION_SUFFIX"]));

	$name = str_replace(array("n", "r"), '', $name);

	if($attachment_name)
		$attachment_name = str_replace(array("n", "r"), '', $attachment_name);
	else
		$attachment_name = $name;

	if(!$force_download)
	{
		if(!static::IsImage($name, $content_type) || $arFile["HEIGHT"] <= 0 || $arFile["WIDTH"] <= 0)
		{
			//only valid images can be downloaded inline
			$force_download = true;
		}
	}

	$content_type = WebMimeType::normalize($content_type);

	if($force_download)
	{
		$specialchars = false;
	}

	$src = null;
	$file = null;

	if ((mb_substr($filename, 0, 1) == '/') && !$fromTemp)
	{
		$file = new IOFile($_SERVER['DOCUMENT_ROOT']. $filename);
	}
	elseif (isset($arFile['tmp_name']))
	{
		$file = new IOFile($arFile['tmp_name']);
	}

	if ((mb_substr($filename, 0, 1) == '/') && ($file instanceof IOFile))
	{
		try
		{
			$src = $file->open(IOFileStreamOpenMode::READ);
		}
		catch(IOIoException $e)
		{
			return false;
		}
	}
	else
	{
		if(!$fastDownload)
		{
			$src = new WebHttpClient();
		}
		elseif(intval($arFile['HANDLER_ID']) > 0)
		{
			$fromClouds = true;
		}
	}

	$APPLICATION->RestartBuffer();

	$cur_pos = 0;
	$filesize = (isset($arFile["FILE_SIZE"]) && (int)$arFile["FILE_SIZE"] > 0 ? (int)$arFile["FILE_SIZE"] : (int)($arFile["size"] ?? 0));
	$size = $filesize-1;
	$p = mb_strpos($_SERVER["HTTP_RANGE"] ?? '', "=");
	if(intval($p)>0)
	{
		$bytes = mb_substr($_SERVER["HTTP_RANGE"], $p + 1);
		$p = mb_strpos($bytes, "-");
		if($p !== false)
		{
			$cur_pos = floatval(mb_substr($bytes, 0, $p));
			$size = floatval(mb_substr($bytes, $p + 1));
			if ($size <= 0)
			{
				$size = $filesize - 1;
			}
			if ($cur_pos > $size)
			{
				$cur_pos = 0;
				$size = $filesize - 1;
			}
		}
	}

	if ($file instanceof IOFile)
	{
		$filetime = $file->getModificationTime();
	}
	elseif(isset($arFile["tmp_name"]) && $arFile["tmp_name"] <> '')
	{
		$tmpFile = new IOFile($arFile["tmp_name"]);
		$filetime = $tmpFile->getModificationTime();
	}
	else
	{
		$filetime = intval(MakeTimeStamp($arFile["TIMESTAMP_X"]));
	}

	$application = BitrixMainApplication::getInstance();
	$response = BitrixMainContext::getCurrent()->getResponse();

	if($_SERVER["REQUEST_METHOD"] == "HEAD")
	{
		$response->setStatus("200 OK")
			->addHeader("Accept-Ranges", "bytes")
			->addHeader("Content-Type", $content_type)
			->addHeader("Content-Length", ($size-$cur_pos+1));

		if($filetime > 0)
		{
			$response->addHeader("Last-Modified", date("r", $filetime));
		}
	}
	else
	{
		$lastModified = '';
		if($cache_time > 0)
		{
			//Handle ETag
			$ETag = md5($filename.$filesize.$filetime);
			if(array_key_exists("HTTP_IF_NONE_MATCH", $_SERVER) && ($_SERVER['HTTP_IF_NONE_MATCH'] === $ETag))
			{
				$response->setStatus("304 Not Modified");
				$response->addHeader("Cache-Control", "private, max-age=".$cache_time.", pre-check=".$cache_time);

				$response->writeHeaders();
				self::terminate();
			}

			$response->addHeader("ETag", $ETag);

			//Handle Last Modified
			if($filetime > 0)
			{
				$lastModified = gmdate('D, d M Y H:i:s', $filetime).' GMT';
				if(array_key_exists("HTTP_IF_MODIFIED_SINCE", $_SERVER) && ($_SERVER['HTTP_IF_MODIFIED_SINCE'] === $lastModified))
				{
					$response->setStatus("304 Not Modified");
					$response->addHeader("Cache-Control", "private, max-age=".$cache_time.", pre-check=".$cache_time);

					$response->writeHeaders();
					self::terminate();
				}
			}
		}

		$utfName = Uri::urnEncode($attachment_name, "UTF-8");
		$translitName = CUtil::translit($attachment_name, LANGUAGE_ID, array(
			"max_len" => 1024,
			"safe_chars" => ".",
			"replace_space" => '-',
			"change_case" => false,
		));

		if($force_download)
		{
			//Disable zlib for old versions of php <= 5.3.0
			//it has broken Content-Length handling
			if(ini_get('zlib.output_compression'))
				ini_set('zlib.output_compression', 'Off');

			if($cur_pos > 0)
			{
				$response->setStatus("206 Partial Content");
			}
			else
			{
				$response->SetStatus("200 OK");
			}

			$response->addHeader("Content-Type", $content_type)
				->addHeader("Content-Disposition", "attachment; filename="".$translitName.""; filename*=utf-8''".$utfName)
				->addHeader("Content-Transfer-Encoding", "binary")
				->addHeader("Content-Length", ($size-$cur_pos+1));

			if(is_resource($src))
			{
				$response->addHeader("Accept-Ranges", "bytes");
				$response->addHeader("Content-Range", "bytes ".$cur_pos."-".$size."/".$filesize);
			}
		}
		else
		{
			$response->addHeader("Content-Type", $content_type);
			$response->addHeader("Content-Disposition", "inline; filename="".$translitName.""; filename*=utf-8''".$utfName);
		}

		if($cache_time > 0)
		{
			$response->addHeader("Cache-Control", "private, max-age=".$cache_time.", pre-check=".$cache_time);
			if($filetime > 0)
			{
				$response->addHeader('Last-Modified', $lastModified);
			}
		}
		else
		{
			$response->addHeader("Cache-Control", "no-cache, must-revalidate, post-check=0, pre-check=0");
		}

		$response->addHeader("Expires", "0");
		$response->addHeader("Pragma", "public");

		$filenameEncoded = Uri::urnEncode($filename, "UTF-8");
		// Download from front-end
		if($fastDownload)
		{
			if($fromClouds)
			{
				$filenameDisableProto = preg_replace('~^(https?)(://)~i', '\1.' , $filenameEncoded);
				$cloudUploadPath = COption::GetOptionString('main', 'bx_cloud_upload', '/upload/bx_cloud_upload/');
				$response->addHeader('X-Accel-Redirect', rawurlencode($cloudUploadPath.$filenameDisableProto));
			}
			else
			{
				$response->addHeader('X-Accel-Redirect', $filenameEncoded);
			}
			$response->writeHeaders();
			self::terminate();
		}
		else
		{
			session_write_close();
			$response->writeHeaders();

			if ($specialchars)
			{
				/** @var IOFile $file */
				echo "<", "pre" ,">";
				if(is_resource($src))
				{
					while(!feof($src))
						echo htmlspecialcharsbx(fread($src, 32768));
					$file->close();
				}
				else
				{
					/** @var WebHttpClient $src */
					echo htmlspecialcharsbx($src->get($filenameEncoded));
				}
				echo "<", "/pre", ">";
			}
			else
			{
				if(is_resource($src))
				{
					/** @var IOFile $file */
					$file->seek($cur_pos);
					while(!feof($src) && ($cur_pos <= $size))
					{
						$bufsize = 131072; //128K
						if($cur_pos + $bufsize > $size)
							$bufsize = $size - $cur_pos + 1;
						$cur_pos += $bufsize;
						echo fread($src, $bufsize);
					}
					$file->close();
				}
				else
				{
					$fp = fopen("php://output", "wb");
					/** @var WebHttpClient $src */
					$src->setOutputStream($fp);
					$src->get($filenameEncoded);
				}
			}
			@ob_flush();
			flush();
			self::terminate();
		}
	}
	return true;
}