Битрикс. Работа с файловой системой
02.11.2018
Теги: CMS • Web-разработка • Битрикс • Директория • Класс • Копировать • НовоеЯдро • Удалить • Файл
За работу с файловой системой в новом ядре отвечают классы пространства имен Bitrix\Main\IO
— IO\Directory
, IO\File
и IO\Path
.
use Bitrix\Main\IO, Bitrix\Main\Application;
Класс IO\File
$file = new IO\File(Application::getDocumentRoot().'/file.txt');
Информация о файле:
$isExist = $file->isExists(); // true, если файл существует $dir = $file->getDirectory(); // директория файла как объект IO\Directory $dir = $file->getDirectoryName(); // директория файла в виде текста $fileName = $file->getName(); // имя файла $fileExt = $file->getExtension(); // расширение файла $fileSize = $file->getSize(); // размер файла в байтах $contentType = $file->getContentType(); // тип файла, Content-type $createdAt = $file->getCreationTime(); // дата создания, timestamp $accessAt = $file->getLastAccessTime(); // дата последнего доступа, timestamp $modifiedAt = $file->getModificationTime(); // дата модификации, timestamp $perms = $file->getPermissions(); // права на файл в виде десятичного числа $perms = substr(sprintf('%o', $file->getPermissions()), -3); // права на файл в виде восьмеричного числа
Действия над файлами:
$content = $file->getContents(); // получить содержание файла $file->putContents('some content'); // записать содержимое в файл с заменой $file->putContents('other content', IO\File::APPEND); // дописать содержимое в конец файла $file->readFile(); // вывести содержимое файла $file->rename(Application::getDocumentRoot().'/new-file.txt'); // переместить/переименовать файл $file->delete(); // удалить файл
У некоторых методов есть статические варианты:
$path = Application::getDocumentRoot().'/file.txt'; IO\File::isFileExists($path); // проверить существование файла IO\File::getFileContents($path); // получить содержание файла IO\File::putFileContents($path, 'some content'); // записать содержимое в файл с заменой IO\File::putFileContents($path, 'other content', self::APPEND); // дописать содержимое в конец файла IO\File::deleteFile($path); // удалить файл
Класс IO\Directory
$dir = new IO\Directory(Application::getDocumentRoot().'/test/');
Если директории не существует, её можно создать:
$dir->create(); // создаёт директорию с указанным в конструкторе путём
Информация о директории:
$isExist = $dir->isExists(); // true, если директория существует $createdAt = $dir->getCreationTime(); // дата создания, timestamp $accessAt = $dir->getLastAccessTime(); // дата последнего доступа, timestamp $modifiedAt = $dir->getModificationTime(); // дата модификации, timestamp $perms = $dir->getPermissions(); // права на директорию в виде десятичного числа $perms = substr(sprintf('%o', $dir->getPermissions()), -3); // права на директорию в виде восьмеричного числа
Действия над директориями:
$childDir = $dir->createSubdirectory('child'); // создает и возвращает вложенную директорию с указанным именем $dir->rename(Application::getDocumentRoot().'/other-path/'); // переместить/переименовать директорию $dir->delete(); // удалить директорию
Получить массив файлов в директории:
$files = $dir->getChildren(); // массив объектов IO\File
У некоторых методов есть статические варианты:
$path = Application::getDocumentRoot().'/some-dir/'; IO\Directory::createDirectory($path); // создать директорию IO\Directory::deleteDirectory($path); // удалить директорию IO\Directory::isDirectoryExists($path); // проверить существование
Класс IO\Path
$path = Application::getDocumentRoot().'/some-dir/some-file.ext'; $fileName = IO\Path::getName($path); // возвращает имя файла $fileDir = IO\Path::getDirectory($path); // возвращает директорию файла (полный путь) $fileExt = IO\Path::getExtension($path); // возвращает расширение файла
Исходные коды
<?php /* * Файл bitrix/modules/main/lib/io/file.php */ namespace Bitrix\Main\IO; class File extends FileEntry implements IFileStream { const REWRITE = 0; const APPEND = 1; /** @var resource */ protected $filePointer; public function __construct($path, $siteId = null) { parent::__construct($path, $siteId); } /** * Opens the file and returns the file pointer. * * @param string $mode * @return resource * @throws FileOpenException */ public function open($mode) { $this->filePointer = fopen($this->getPhysicalPath(), $mode."b"); if (!$this->filePointer) { throw new FileOpenException($this->originalPath); } return $this->filePointer; } /** * Closes the file. * * @throws FileNotOpenedException */ public function close() { if(!$this->filePointer) { throw new FileNotOpenedException($this->originalPath); } fclose($this->filePointer); $this->filePointer = null; } public function isExists() { $p = $this->getPhysicalPath(); return file_exists($p) && (is_file($p) || is_link($p)); } public function getContents() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); return file_get_contents($this->getPhysicalPath()); } public function putContents($data, $flags = self::REWRITE) { $dir = $this->getDirectory(); if (!$dir->isExists()) $dir->create(); if ($this->isExists() && !$this->isWritable()) $this->markWritable(); return $flags & self::APPEND ? file_put_contents($this->getPhysicalPath(), $data, FILE_APPEND) : file_put_contents($this->getPhysicalPath(), $data); } /** * Returns the file size. * * @return float|int * @throws FileNotFoundException * @throws FileOpenException */ public function getSize() { if (!$this->isExists()) { throw new FileNotFoundException($this->originalPath); } static $supportLarge32 = null; if($supportLarge32 === null) { $supportLarge32 = (\Bitrix\Main\Config\Configuration::getValue("large_files_32bit_support") === true); } $size = 0; if(PHP_INT_SIZE < 8 && $supportLarge32) { // 32bit $this->open(FileStreamOpenMode::READ); if(fseek($this->filePointer, 0, SEEK_END) === 0) { $size = 0.0; $step = 0x7FFFFFFF; while($step > 0) { if (fseek($this->filePointer, -$step, SEEK_CUR) === 0) { $size += floatval($step); } else { $step >>= 1; } } } $this->close(); } else { // 64bit $size = filesize($this->getPhysicalPath()); } return $size; } /** * Seeks on the file pointer from the beginning (SEEK_SET only). * * @param int|float $position * @return int * @throws FileNotOpenedException */ public function seek($position) { if(!$this->filePointer) { throw new FileNotOpenedException($this->originalPath); } if($position <= PHP_INT_MAX) { return fseek($this->filePointer, $position, SEEK_SET); } else { $res = fseek($this->filePointer, 0, SEEK_SET); if($res === 0) { do { $offset = ($position < PHP_INT_MAX? $position : PHP_INT_MAX); $res = fseek($this->filePointer, $offset, SEEK_CUR); if($res !== 0) { break; } $position -= PHP_INT_MAX; } while($position > 0); } return $res; } } public function isWritable() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); return is_writable($this->getPhysicalPath()); } public function isReadable() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); return is_readable($this->getPhysicalPath()); } public function readFile() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); return readfile($this->getPhysicalPath()); } public function getCreationTime() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); return filectime($this->getPhysicalPath()); } public function getLastAccessTime() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); return fileatime($this->getPhysicalPath()); } public function getModificationTime() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); return filemtime($this->getPhysicalPath()); } public function markWritable() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); @chmod($this->getPhysicalPath(), BX_FILE_PERMISSIONS); } public function getPermissions() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); return fileperms($this->getPhysicalPath()); } public function delete() { if ($this->isExists()) return unlink($this->getPhysicalPath()); return true; } public function getContentType() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); $finfo = \finfo_open(FILEINFO_MIME_TYPE); $contentType = \finfo_file($finfo, $this->getPath()); \finfo_close($finfo); return $contentType; } public static function isFileExists($path) { $f = new self($path); return $f->isExists(); } public static function getFileContents($path) { $f = new self($path); return $f->getContents(); } public static function putFileContents($path, $data, $flags=self::REWRITE) { $f = new self($path); return $f->putContents($data, $flags); } public static function deleteFile($path) { $f = new self($path); return $f->delete(); } }
<?php /* * Файл bitrix/modules/main/lib/io/directory.php */ namespace Bitrix\Main\IO; class Directory extends DirectoryEntry { public function __construct($path, $siteId = null) { parent::__construct($path, $siteId); } public function isExists() { $p = $this->getPhysicalPath(); return file_exists($p) && is_dir($p); } public function delete() { return self::deleteInternal($this->getPhysicalPath()); } private static function deleteInternal($path) { if (is_file($path) || is_link($path)) { if (!@unlink($path)) throw new FileDeleteException($path); } elseif (is_dir($path)) { if ($handle = opendir($path)) { while (($file = readdir($handle)) !== false) { if ($file == "." || $file == "..") continue; self::deleteInternal(Path::combine($path, $file)); } closedir($handle); } if (!@rmdir($path)) throw new FileDeleteException($path); } return true; } /** * @return array|FileSystemEntry[] * @throws FileNotFoundException */ public function getChildren() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); $arResult = array(); if ($handle = opendir($this->getPhysicalPath())) { while (($file = readdir($handle)) !== false) { if ($file == "." || $file == "..") continue; $pathLogical = Path::combine($this->path, Path::convertPhysicalToLogical($file)); $pathPhysical = Path::combine($this->getPhysicalPath(), $file); if (is_dir($pathPhysical)) $arResult[] = new Directory($pathLogical); else $arResult[] = new File($pathLogical); } closedir($handle); } return $arResult; } /** * @param $name * @return Directory|DirectoryEntry */ public function createSubdirectory($name) { $dir = new Directory(Path::combine($this->path, $name)); if (!$dir->isExists()) mkdir($dir->getPhysicalPath(), BX_DIR_PERMISSIONS, true); return $dir; } public function getCreationTime() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); return filectime($this->getPhysicalPath()); } public function getLastAccessTime() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); return fileatime($this->getPhysicalPath()); } public function getModificationTime() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); return filemtime($this->getPhysicalPath()); } public function markWritable() { if (!$this->isExists()) throw new FileNotFoundException($this->originalPath); @chmod($this->getPhysicalPath(), BX_DIR_PERMISSIONS); } public function getPermissions() { return fileperms($this->getPhysicalPath()); } /** * @param $path * * @return Directory */ public static function createDirectory($path) { $dir = new self($path); $dir->create(); return $dir; } public static function deleteDirectory($path) { $dir = new self($path); $dir->delete(); } public static function isDirectoryExists($path) { $f = new self($path); return $f->isExists(); } }
<?php /* * Файл bitrix/modules/main/lib/io/path.php */ namespace Bitrix\Main\IO; use Bitrix\Main; use Bitrix\Main\Text; class Path { const DIRECTORY_SEPARATOR = '/'; const DIRECTORY_SEPARATOR_ALT = '\\'; const PATH_SEPARATOR = PATH_SEPARATOR; const INVALID_FILENAME_CHARS = "\\/:*?\"'<>|~#&;"; // the pattern should be quoted, "|" is allowed below as a delimiter const INVALID_FILENAME_BYTES = "\xE2\x80\xAE"; // Right-to-Left Override Unicode Character protected static $physicalEncoding = ""; protected static $logicalEncoding = ""; protected static $directoryIndex = null; public static function normalize($path) { if (!is_string($path) || ($path == "")) return null; // slashes does not matter for Windows static $pattern = null, $tailPattern; if (!$pattern) { if(strncasecmp(PHP_OS, "WIN", 3) == 0) { // windows $pattern = "'[\\\\/]+'"; $tailPattern = "\0.\\/+ "; } else { // unix $pattern = "'[/]+'"; $tailPattern = "\0/"; } } $pathTmp = preg_replace($pattern, "/", $path); if (strpos($pathTmp, "\0") !== false) throw new InvalidPathException($path); if (preg_match("#(^|/)(\\.|\\.\\.)(/|\$)#", $pathTmp)) { $arPathTmp = explode('/', $pathTmp); $arPathStack = array(); foreach ($arPathTmp as $i => $pathPart) { if ($pathPart === '.') continue; if ($pathPart === "..") { if (array_pop($arPathStack) === null) throw new InvalidPathException($path); } else { array_push($arPathStack, $pathPart); } } $pathTmp = implode("/", $arPathStack); } $pathTmp = rtrim($pathTmp, $tailPattern); if (substr($path, 0, 1) === "/" && substr($pathTmp, 0, 1) !== "/") $pathTmp = "/".$pathTmp; if ($pathTmp === '') $pathTmp = "/"; return $pathTmp; } public static function getExtension($path) { $path = self::getName($path); if ($path != '') { $pos = Text\UtfSafeString::getLastPosition($path, '.'); if ($pos !== false) return substr($path, $pos + 1); } return ''; } public static function getName($path) { // $path = self::normalize($path); $p = Text\UtfSafeString::getLastPosition($path, self::DIRECTORY_SEPARATOR); if ($p !== false) return substr($path, $p + 1); return $path; } public static function getDirectory($path) { return substr($path, 0, -strlen(self::getName($path)) - 1); } public static function convertLogicalToPhysical($path) { if (self::$physicalEncoding == "") self::$physicalEncoding = self::getPhysicalEncoding(); if (self::$logicalEncoding == "") self::$logicalEncoding = self::getLogicalEncoding(); if (self::$physicalEncoding == self::$logicalEncoding) return $path; return Text\Encoding::convertEncoding($path, self::$logicalEncoding, self::$physicalEncoding); } public static function convertPhysicalToLogical($path) { if (self::$physicalEncoding == "") self::$physicalEncoding = self::getPhysicalEncoding(); if (self::$logicalEncoding == "") self::$logicalEncoding = self::getLogicalEncoding(); if (self::$physicalEncoding == self::$logicalEncoding) return $path; return Text\Encoding::convertEncoding($path, self::$physicalEncoding, self::$logicalEncoding); } public static function convertLogicalToUri($path) { if (self::$logicalEncoding == "") self::$logicalEncoding = self::getLogicalEncoding(); if (self::$directoryIndex == null) self::$directoryIndex = self::getDirectoryIndexArray(); if (isset(self::$directoryIndex[self::getName($path)])) $path = self::getDirectory($path)."/"; if ('utf-8' !== self::$logicalEncoding) $path = Text\Encoding::convertEncoding($path, self::$logicalEncoding, 'utf-8'); return implode('/', array_map("rawurlencode", explode('/', $path))); } public static function convertPhysicalToUri($path) { if (self::$physicalEncoding == "") self::$physicalEncoding = self::getPhysicalEncoding(); if (self::$directoryIndex == null) self::$directoryIndex = self::getDirectoryIndexArray(); if (isset(self::$directoryIndex[self::getName($path)])) $path = self::getDirectory($path)."/"; if ('utf-8' !== self::$physicalEncoding) $path = Text\Encoding::convertEncoding($path, self::$physicalEncoding, 'utf-8'); return implode('/', array_map("rawurlencode", explode('/', $path))); } public static function convertUriToPhysical($path) { if (self::$physicalEncoding == "") self::$physicalEncoding = self::getPhysicalEncoding(); if (self::$directoryIndex == null) self::$directoryIndex = self::getDirectoryIndexArray(); $path = implode('/', array_map("rawurldecode", explode('/', $path))); if ('utf-8' !== self::$physicalEncoding) $path = Text\Encoding::convertEncoding($path, 'utf-8', self::$physicalEncoding); return $path; } protected static function getLogicalEncoding() { if (defined('BX_UTF')) $logicalEncoding = "utf-8"; elseif (defined("SITE_CHARSET") && (strlen(SITE_CHARSET) > 0)) $logicalEncoding = SITE_CHARSET; elseif (defined("LANG_CHARSET") && (strlen(LANG_CHARSET) > 0)) $logicalEncoding = LANG_CHARSET; elseif (defined("BX_DEFAULT_CHARSET")) $logicalEncoding = BX_DEFAULT_CHARSET; else $logicalEncoding = "windows-1251"; return strtolower($logicalEncoding); } protected static function getPhysicalEncoding() { $physicalEncoding = defined("BX_FILE_SYSTEM_ENCODING") ? BX_FILE_SYSTEM_ENCODING : ""; if ($physicalEncoding == "") { if (strtoupper(substr(PHP_OS, 0, 3)) === "WIN") $physicalEncoding = "windows-1251"; else $physicalEncoding = "utf-8"; } return strtolower($physicalEncoding); } public static function combine() { $numArgs = func_num_args(); if ($numArgs <= 0) return ""; $arParts = array(); for ($i = 0; $i < $numArgs; $i++) { $arg = func_get_arg($i); if (is_array($arg)) { if (empty($arg)) continue; foreach ($arg as $v) { if (!is_string($v) || $v == "") continue; $arParts[] = $v; } } elseif (is_string($arg)) { if ($arg == "") continue; $arParts[] = $arg; } } $result = ""; foreach ($arParts as $part) { if ($result !== "") $result .= self::DIRECTORY_SEPARATOR; $result .= $part; } $result = self::normalize($result); return $result; } public static function convertRelativeToAbsolute($relativePath) { if (!is_string($relativePath)) throw new Main\ArgumentTypeException("relativePath", "string"); if ($relativePath == "") throw new Main\ArgumentNullException("relativePath"); return self::combine($_SERVER["DOCUMENT_ROOT"], $relativePath); } public static function convertSiteRelativeToAbsolute($relativePath, $site = null) { if (!is_string($relativePath) || $relativePath == "") $site = SITE_ID; $basePath = Main\SiteTable::getDocumentRoot($site); return self::combine($basePath, $relativePath); } protected static function validateCommon($path) { if (!is_string($path)) { return false; } if (trim($path) == "") { return false; } if (strpos($path, "\0") !== false) { return false; } if(preg_match("#(".self::INVALID_FILENAME_BYTES.")#", $path)) { return false; } return true; } public static function validate($path) { if(!static::validateCommon($path)) { return false; } return (preg_match("#^([a-z]:)?/([^\x01-\x1F".preg_quote(self::INVALID_FILENAME_CHARS, "#")."]+/?)*$#isD", $path) > 0); } public static function validateFilename($filename) { if(!static::validateCommon($filename)) { return false; } return (preg_match("#^[^\x01-\x1F".preg_quote(self::INVALID_FILENAME_CHARS, "#")."]+$#isD", $filename) > 0); } /** * @param string $filename * @param callable $callback * @return string */ public static function replaceInvalidFilename($filename, $callback) { return preg_replace_callback( "#([\x01-\x1F".preg_quote(self::INVALID_FILENAME_CHARS, "#")."]|".self::INVALID_FILENAME_BYTES.")#", $callback, $filename ); } /** * @param string $filename * @return string */ public static function randomizeInvalidFilename($filename) { return static::replaceInvalidFilename($filename, function() { return chr(rand(97, 122)); } ); } public static function isAbsolute($path) { return (substr($path, 0, 1) === "/") || preg_match("#^[a-z]:/#i", $path); } protected static function getDirectoryIndexArray() { static $directoryIndexDefault = array( "index.php" => 1, "index.html" => 1, "index.htm" => 1, "index.phtml" => 1, "default.html" => 1, "index.php3" => 1 ); $directoryIndex = Main\Config\Configuration::getValue("directory_index"); if ($directoryIndex !== null) return $directoryIndex; return $directoryIndexDefault; } }
Поиск: CMS • Web-разработка • Битрикс • Директория • Класс • Копировать • Удалить • Файл • IO\Directory • IO\File • IO\Path • createDirectory • deleteDirectory • isDirectoryExists • getDocumentRoot • isFileExists • getFileContents • putFileContents • deleteFile • getDirectory