Функция readfile в php проверяет существует ли файл
Прочитав эту статью, вы узнаете, как создавать, получать доступ и управлять файлами на веб-сервере с помощью функции PHP fread и другими.
Функции файловой системы PHP
В приведенной ниже таблице представлен обзор других полезных функций, которые можно использовать для динамического чтения и записи файлов ( альтернатива PHP fread() и другим функциям ):
На платформах Windows, для проверки наличия файлов на сетевых ресурсах, используйте имена, подобные //computername/share/filename или \\computername\share\filename .
User Contributed Notes 36 notes
Just a note for those who face problems on names containing spaces (e.g. "test test.pdf").
In the examples (99% of the time) you can find
header('Content-Disposition: attachment; filename='.basename($file));
but the correct way to set the filename is quoting it (double quote):
header('Content-Disposition: attachment; filename="'.basename($file).'"' );
flobee.at.gmail.dot.com shared "readfile_chunked" function. It does work, but you may encounter memory exhaustion using "fread". Meanwhile "stream_copy_to_stream" seems to utilize the same amount of memory as "readfile". At least, when I was testing "download" function for my https://github.com/Simbiat/HTTP20 library on 1.5G file with 256M memory limitation that was the case: "fread" I got peak memory usage of ~240M, while with "stream_copy_to_stream" - ~150M.
It does not mean that you can fully escape memory exhaustion, though: if you are reading too much at a time, you can still encounter it. That is why in my library I use a helper function ("speedLimit") to calculate whether selected speed limit will fit the available memory (while allowing some headroom).
You can read comments in the code itself for more details and raise issues for the library, if you think something is incorrect there (especially since it's WIP at the moment of writing this), but so far I am able to get consistent behavior with it.
if you need to limit download rate, use this code
$local_file = 'file.zip' ;
$download_file = 'name.zip' ;
// set the download rate limit (=> 20,5 kb/s)
$download_rate = 20.5 ;
if( file_exists ( $local_file ) && is_file ( $local_file ))
header ( 'Cache-control: private' );
header ( 'Content-Type: application/octet-stream' );
header ( 'Content-Length: ' . filesize ( $local_file ));
header ( 'Content-Disposition: filename=' . $download_file );
flush ();
$file = fopen ( $local_file , "r" );
while(! feof ( $file ))
// send the current file part to the browser
print fread ( $file , round ( $download_rate * 1024 ));
// flush the content to the browser
flush ();
// sleep one second
sleep ( 1 );
>
fclose ( $file );>
else die( 'Error: The file ' . $local_file . ' does not exist!' );
>
regarding php5:
i found out that there is already a disscussion @php-dev about readfile() and fpassthru() where only exactly 2 MB will be delivered.
so you may use this on php5 to get lager files
function readfile_chunked ( $filename , $retbytes = true ) $chunksize = 1 *( 1024 * 1024 ); // how many bytes per chunk
$buffer = '' ;
$cnt = 0 ;
// $handle = fopen($filename, 'rb');
$handle = fopen ( $filename , 'rb' );
if ( $handle === false ) return false ;
>
while (! feof ( $handle )) $buffer = fread ( $handle , $chunksize );
echo $buffer ;
if ( $retbytes ) $cnt += strlen ( $buffer );
>
>
$status = fclose ( $handle );
if ( $retbytes && $status ) return $cnt ; // return num. bytes delivered like readfile() does.
>
return $status ;
My script working correctly on IE6 and Firefox 2 with any typ e of files (I hope :))
function DownloadFile($file) < // $file = include path
if(file_exists($file)) header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
>
Run on Apache 2 (WIN32) PHP5
To avoid the risk of choosing themselves which files to download by messing with the request and doing things like inserting "../" into the "filename", simply remember that URLs are not file paths, and there's no reason why the mapping between them has to be so literal as "download.php?file=thingy.mpg" resulting in the download of the file "thingy.mpg".
It's your script and you have full control over how it maps file requests to file names, and which requests retrieve which files.
But even then, as ever, never trust ANYTHING in the request. Basic first-day-at-school security principle, that.
Always using MIME-Type 'application/octet-stream' is not optimal. Most if not all browsers will simply download files with that type.
If you use proper MIME types (and inline Content-Disposition), browsers will have better default actions for some of them. Eg. in case of images, browsers will display them, which is probably what you'd want.
To deliver the file with the proper MIME type, the easiest way is to use:
header('Content-Type: ' . mime_content_type($file));
header('Content-Disposition: inline; filename="'.basename($file).'"');
A note on the smartReadFile function from gaosipov:
Change the indexes on the preg_match matches to:
$begin = intval($matches[1]);
if( !empty($matches[2]) ) $end = intval($matches[2]);
>
Otherwise the $begin would be set to the entire section matched and the $end to what should be the begin.
See preg_match for more details on this.
To anyone that's had problems with Readfile() reading large files into memory the problem is not Readfile() itself, it's because you have output buffering on. Just turn off output buffering immediately before the call to Readfile(). Use something like ob_end_flush().
To avoid errors,
just be careful whether slash "/" is allowed or not at the beginning of $file_name parameter.
In my case, trying to send PDF files thru PHP after access-logging,
the beginning "/" must be removed in PHP 7.1.
$size = filesize ( $location );
$time = date ( 'r' , filemtime ( $location ));
$begin = 0 ;
$end = $size ;
header ( "Content-Type: $mimeType " );
header ( 'Cache-Control: public, must-revalidate, max-age=0' );
header ( 'Pragma: no-cache' );
header ( 'Accept-Ranges: bytes' );
header ( 'Content-Length:' .( $end - $begin ));
header ( "Content-Range: bytes $begin - $end / $size " );
header ( "Content-Disposition: inline; filename= $filename " );
header ( "Content-Transfer-Encoding: binary\n" );
header ( "Last-Modified: $time " );
header ( 'Connection: close' );
$cur = $begin ;
fseek ( $fm , $begin , 0 );
smartReadFile ( "/tmp/filename" , "myfile.mp3" , "audio/mpeg" )
?>
It can be slow for big files to read by fread, but this is a single way to read file in strict bounds. You can modify this and add fpassthru instead of fread and while, but it sends all data from begin --- it would be not fruitful if request is bytes from 100 to 200 from 100mb file.
When using the readfile_chunked function noted here with files larger than 10MB or so I am still having memory errors. It's because the writers have left out the all important flush() after each read. So this is the proper chunked readfile (which isn't really readfile at all, and should probably be crossposted to passthru(), fopen(), and popen() just so browsers can find this information):
function readfile_chunked ( $filename , $retbytes = true ) <
$chunksize = 1 *( 1024 * 1024 ); // how many bytes per chunk
$buffer = '' ;
$cnt = 0 ;
// $handle = fopen($filename, 'rb');
$handle = fopen ( $filename , 'rb' );
if ( $handle === false ) <
return false ;
>
while (! feof ( $handle )) <
$buffer = fread ( $handle , $chunksize );
echo $buffer ;
ob_flush ();
flush ();
if ( $retbytes ) <
$cnt += strlen ( $buffer );
>
>
$status = fclose ( $handle );
if ( $retbytes && $status ) <
return $cnt ; // return num. bytes delivered like readfile() does.
>
return $status ;
>
?>
All I've added is a flush(); after the echo line. Be sure to include this!
If you are lucky enough to not be on shared hosting and have apache, look at installing mod_xsendfile.
This was the only way I found to both protect and transfer very large files with PHP (gigabytes).
It's also proved to be much faster for basically any file.
Available directives have changed since the other note on this and XSendFileAllowAbove was replaced with XSendFilePath to allow more control over access to files outside of webroot.
Download the source.
Install with: apxs -cia mod_xsendfile.c
Then to use it in your script:
$file = '/tmp/blah/foo.iso' ;
$download_name = basename ( $file );
if ( file_exists ( $file )) header ( 'Content-Type: application/octet-stream' );
header ( 'Content-Disposition: attachment; filename=' . $download_name );
header ( 'X-Sendfile: ' . $file );
exit;
>
?>
Just a note: If you're using bw_mod (current version 0.6) to limit bandwidth in Apache 2, it *will not* limit bandwidth during readfile events.
Instead of using
header ( 'Content-Type: application/force-download' );
?>
use
header ( 'Content-Type: application/octet-stream' );
?>
Some browsers have troubles with force-download.
Using pieces of the forced download script, adding in MySQL database functions, and hiding the file location for security was what we needed for downloading wmv files from our members creations without prompting Media player as well as secure the file itself and use only database queries. Something to the effect below, very customizable for private access, remote files, and keeping order of your online media.
switch ($file_extension) <
case "wmv": $ctype="video/x-ms-wmv"; break;
default: $ctype="application/force-download";
>
// required for IE, otherwise Content-disposition is ignored
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: video/x-ms-wmv");
header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=\"".basename($filename)."\";");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".@filesize($filename));
set_time_limit(0);
@readfile("$fileurl") or die("File not found.");
$donwloaded = "downloads + 1";
if ($_GET["hit"]) <
mysql_query("UPDATE ibf_movies SET downloads = $donwloaded WHERE ");
If you are looking for an algorithm that will allow you to download (force download) a big file, may this one will help you.
$filename = "file.csv";
$filepath = "/path/to/file/" . $filename;
// Close sessions to prevent user from waiting until
// download will finish (uncomment if needed)
//session_write_close();
set_time_limit(0);
ignore_user_abort(false);
ini_set('output_buffering', 0);
ini_set('zlib.output_compression', 0);
$chunk = 10 * 1024 * 1024; // bytes per chunk (10 MB)
$fh = fopen($filepath, "rb");
if ($fh === false) <
echo "Unable open file";
>
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
// Repeat reading until EOF
while (!feof($fh)) <
echo fread($handle, $chunk);
ob_flush(); // flush output
flush();
>
A mime-type-independent forced download can also be conducted by using:
(. )
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // some day in the past
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Content-type: application/x-download");
header("Content-Disposition: attachment; filename=");
header("Content-Transfer-Encoding: binary");
?>
Remember if you make a "force download" script like mentioned below that you SANITIZE YOUR INPUT!
I have seen a lot of download scripts that does not test so you are able to download anything you want on the server.
Test especially for strings like ".." which makes directory traversal possible. If possible only permit characters a-z, A-Z and 0-9 and make it possible to only download from one "download-folder".
In the C source, this function simply opens the path in read+binary mode, without a lock, and uses fpassthru()
If you need a locked read, use fopen(), flock(), and then fpassthru() directly.
I have noticed some unusual behavior with Internet Explorer 6 that’s worth taking note of. I have a link on my site to a script that outputs an XML file to the browser with the below code:
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$filename.'"');
@readfile($file);
When the popular IE setting “Reuse Window for Launching Shortcuts” is unchecked (access this setting in the Tools Menu > Internet Options > Advanced Tab) this script will output the file to the browser and open it in a different window if the user clicks the open button on the IE prompt. However, if this setting is checked, and browser windows are being re-used, then it will open up on top of the page where the link was clicked to access the script.
If I instead set the html link target option to be “_blank”, the script will open up in a new window as expected if the “Reuse Window for Launching Shortcuts” is checked. But, if the setting is unchecked, the output XML file will open up in a new window and there will be another blank window also open that has the address of the script, in addition to our original window.
This is far from ideal, and there is no way of knowing whether users have this option checked or not. We are stuck with the distinct possibility of half of our visitors seeing either an annoying third blank window being opened or the script writing over their original window, depending on their “Reuse Window for Launching Shortcuts” setting.
That is one way to do it, however this is avoidable. For example in Zend Framework you could do
// Action controller
public function someAction ()
$response = $this -> _response ;
// Disable view and layout rendering
$this -> _helper -> viewRenderer -> setNoRender ();
$this -> _helper -> layout ()-> disableLayout ();
// Process the file
$file = 'whatever.zip' ;
$bits = @ file_get_contents ( $file );
if( strlen ( $bits ) == 0 ) $response -> setBody ( 'Sorry, we could not find requested download file.' );
>
else $response -> setHeader ( 'Content-type' , 'application/octet-stream' , true );
$response -> setBody ( $bits );
>
>
If you guys know how to judge the return values of function "stat", in order to avoid using "is_file" or "is_readable" (or "is_dir"), please let me know or just write it here.
If you don't have to do anything special on 404, "header('HTTP/1.x xxx xxxxx');" can be inside of the function.
$stat = @ stat ( $filename );
$etag = sprintf ( '%x-%x-%x' , $stat [ 'ino' ], $stat [ 'size' ], $stat [ 'mtime' ] * 1000000 );
header ( 'Expires: ' );
header ( 'Cache-Control: ' );
header ( 'Pragma: ' );
Описание родственных функций вы сможете найти в разделах Каталоги и Выполнение программ.
За списком обёрток URL для работы с удалёнными файлами и пояснениями обращайтесь к главе Поддерживаемые протоколы и обёртки.
Возвращаемые значения
Возвращает true , если файл или каталог, указанный параметром filename , существует, иначе возвращает false .
Замечание:
Данная функция возвращает false для символических ссылок, указывающих на несуществующие файлы.
Замечание:
Проверка происходит с помощью реальных UID/GID, а не эффективных идентификаторов.
Замечание: Так как тип integer в PHP является целым числом со знаком, и многие платформы используют 32-х битные целые числа, то некоторые функции файловых систем могут возвращать неожиданные результаты для файлов размером больше 2 Гб.
Содержание
Чтение из файлов с помощью функции PHP fread()
Теперь вы знаете, как открывать и закрывать файлы. В следующем разделе вы узнаете, как читать данные из файла. PHP включает в себя сразу несколько функций для чтения данных из файла. За одну операцию можно считать, как один символ, так и весь файл.
Примеры
Результатом выполнения данного примера будет что-то подобное:
Открытие файла с помощью функции PHP fopen()
Для работы с файлом сначала нужно его открыть функцией fopen() . Ее синтаксис:
Первый параметр, передаваемый в fopen() , это имя файла, который нужно открыть, а второй - режим открытия. Например:
Файл может быть открыт в одном из следующих режимов:
Режим | Что он делает |
R | Открывает файл только для чтения. |
r+ | Открывает файл для чтения и записи. |
W | Открывает файл только для записи и очищает содержимое файла. Если файл не существует, PHP попытается его создать. |
w+ | Открывает файл для чтения и записи и очищает содержимое файла. Если файл не существует, PHP попытается его создать. |
A | Открывает файл только для записи. Сохраняет содержимое файла, записывая его в конец файла. Если файл не существует, PHP попытается его создать. |
a+ | Открывает файл для чтения и записи. Сохраняет содержимое файла, записывая его в конец файла. Если файл не существует, он будет создан. Можно использовать вместо PHP fread () |
X | Открывает файл только для записи. Возвращает значение FALSE и генерирует ошибку, если файл уже существует. Если файл не существует, PHP попытается его создать. |
x+ | Открывает файл для чтения и записи; в противном случае имеет такое же поведение, как «x». |
Совет . Операции с файлами и папками часто сопряжены с ошибками. Поэтому рекомендуется применить форму проверки ошибок, чтобы при их возникновении скрипт обработал ошибку.
Смотрите также
- fpassthru() - Выводит все оставшиеся данные из файлового указателя
- file() - Читает содержимое файла и помещает его в массив
- fopen() - Открывает файл или URL
- include - include
- require - require
- virtual() - Выполняет подзапрос Apache
- file_get_contents() - Читает содержимое файла в строку
Запись файлов с использованием функции PHP fwrite()
Можно записать данные в файл с помощью функции PHP fwrite() . Ее синтаксис:
Функция fwrite() принимает два параметра: дескриптор файла и строку данных, которые должны быть записаны:
В приведенном выше примере, если файл note.txt не существует, PHP автоматически создаст его и запишет данные. Но если note.txt уже существует, PHP перед записью новых данных стирает содержимое этого файла. Если вы просто хотите добавить файл и сохранить существующее содержимое, используйте режим a вместо w .
Альтернативный способ – file_put_contents() . Это аналог функции file_get_contents() , который предоставляет простой способ записи данных в файл без необходимости его открытия. Эта функция принимает имя и путь к файлу с данными, которые должны быть записаны. Например ( похожий на PHP fread пример ):
Если файл, указанный в функции file_put_contents() , уже существует, PHP по умолчанию перезапишет его. Если вы хотите сохранить содержимое файла, можно передать специальный флаг FILE_APPEND в качестве третьего параметра file_put_contents() . Тогда функция добавит новые данные в файл, а не перепишет их. Пример:
Ошибки
В случае неудачного завершения работы генерируется ошибка уровня E_WARNING .
Примечания
Замечание:
readfile() сама по себе не приводит к каким-либо проблемам с памятью, даже при отправке больших файлов. При возникновении ошибки превышения памяти убедитесь, что буферизация вывода отключена с помощью ob_get_level() .
Для этой функции вы можете использовать URL в качестве имени файла, если была включена опция fopen wrappers. Смотрите более подробную информацию об определении имени файла в описании функции fopen() . Смотрите также список поддерживаемых обёрток URL, их возможности, замечания по использованию и список предопределённых констант в разделе Поддерживаемые протоколы и обёртки.
Закрытие файла
Как только вы закончите чтение файла с помощью PHP fread , его нужно закрыть. Для этого используется функция fclose() :
Примечание . Хотя PHP автоматически закрывает все открытые файлы, когда скрипт завершается, рекомендуется закрыть файл после выполнения всех операций.
User Contributed Notes 8 notes
I just learned that, to specify file names in a portable manner, you DON'T need 'DIRECTORY_SEPARATOR' - just use '/'. This really surprised and shocked me, as until now I typed about a zillion times 'DIRECTORY_SEPARATOR' to stay platform independent - unnecessary. Don't make the same mistake.
You have an array of directories (straightforward list of directories):
$array = array(
'/home/drapeko/var' ,
'/home/drapeko/var/y' ,
'/home/drapeko' ,
'/home' ,
'/var/libexec'
);
);
?>
And you would like to transform this array to hierarchy of directories:
$array = array (
'home' => array (
'drapeko' => array (
'var' => array (
'y' => array()
)
)
),
'var' => array(
'libexec' => array()
)
);
?>
How can you do it?
First of all the below function will help us.
/**
* This function converts real filesystem path to the string array representation.
*
* for example,
* '/home/drapeko/var/y will be converted to $result_array['home']['drapeko']['var']['y']
* '/home/drapeko/var/y/file.txt will be converted to $result_array['home']['drapeko']['var']['y']
*
* @param $path realpath of the directory
* @return string string array representation of the path
*/
function pathToArrayStr ( $path ) <
// TODO constants/configs?
$res_path = str_replace (array( ':/' , ':\\' , '/' , '\\' , DIRECTORY_SEPARATOR ), '/' , $path );
// if the first or last symbol is '/' delete it (e.g. for linux)
$res_path = preg_replace (array( "/^\//" , "/\/$/" ), '' , $res_path );
// create string
$res_path = '[\'' . str_replace ( '/' , '\'][\'' , $res_path ). '\']' ;
return $res_path ;
>
?>
It simply converts the real path of the file to array string representation.
How can you use this function? I know it looks like a little confusing. But it's quite simple. Consider the example below:
$result = array();
$check = array();
foreach( $array as $val ) <
$str = pathToArrayStr ( $val , 'result' );
foreach( $check as $ck ) <
if ( strpos ( $ck , $str ) !== false ) <
continue 2 ;
>
>
$check [] = $str ;
eval( '$result' . $str . ' = array();' );
>
print_r ( $result );
?>
Heh, how do you find it? This approach has helped me very much. I hope you will find it useful. :)
I made this function to search and/or display files by extension or for a string occurance in the filename. Any comments or enhancements are welcome offcourse. I'll update this function soon.
usage: list_files([string], [string], [int 1 | 0], [int 1 | 0]);
search for extension: list_files([string], [string], [0], [int 1 | 0]);
returns array: $myArray = list_files([string], [string], [0], [0]);
echo result: list_files([string], [string], [0], [1]);
search for string occurance: list_files([string], [string], [1], [int 1 | 0]);
returns array: $myArray = list_files([string], [string], [1], [0]);
echo result: list_files([string], [string], [1], [1]);
function list_files ( $directory , $stringSearch , $searchHandler , $outputHandler ) $errorHandler = false ;
$result = array();
if (! $directoryHandler = @ opendir ( $directory )) echo ( "
\nerror: directory \" $directory \" doesn't exist!\n\n" );
return $errorHandler = true ;
>
if ( $searchHandler === 0 ) while ( false !== ( $fileName = @ readdir ( $directoryHandler ))) if(@ substr ( $fileName , - @ strlen ( $stringSearch )) === $stringSearch ) @ array_push ( $result , $fileName );
>
>
>
if ( $searchHandler === 1 ) while( false !== ( $fileName = @ readdir ( $directoryHandler ))) if(@ substr_count ( $fileName , $stringSearch ) > 0 ) @ array_push ( $result , $fileName );
>
>
>
if (( $errorHandler === true ) && (@ count ( $result ) === 0 )) echo ( "
\nerror: no filetype \" $fileExtension \" found!\n\n" );
>
else sort ( $result );
if ( $outputHandler === 0 ) return $result ;
>
if ( $outputHandler === 1 ) echo ( "
\n" );\n" );
print_r ( $result );
echo ( "
>
>
>
This function searches a directory and returns an array of all files whose filename matches the specified regular expression. It's similar in concept to the Unix find program.
function findfile($location='',$fileregex='') if (!$location or !is_dir($location) or !$fileregex) return false;
>
$all = opendir($location);
while ($file = readdir($all)) if (is_dir($location.'/'.$file) and $file <> ".." and $file <> ".") $subdir_matches = findfile($location.'/'.$file,$fileregex);
$matchedfiles = array_merge($matchedfiles,$subdir_matches);
unset($file);
>
elseif (!is_dir($location.'/'.$file)) if (preg_match($fileregex,$file)) array_push($matchedfiles,$location.'/'.$file);
>
>
>
closedir($all);
unset($all);
return $matchedfiles;
>
ini_set ( 'auto_detect_line_endings' , true );
$contents = file ( 'unknowntype.txt' );
ini_set ( 'auto_detect_line_endings' , false );
$content2 = file ( 'unixfile.txt' );
?>
Note, with PHP 4.3 anytime Mac files are read using fgets or file you'll need to auto_detect_line_endings since \n is otherwise assumed. However, with PHP 5.0, stream_get_line() will allow you to specify what line ending character to read up to.
\\ Read a line from a MAC file
stream_get_line($fp, 4096, "\r");
\\ Read a line from a UNIX file
stream_get_line($fp, 4096, "\n");
\\ Read a line from a DOS file
stream_get_line($fp, 4096, "\r\n");
\\ Read a line up to any filesystem line ending
ini_set('auto_detect_line_endings', true); fgets($fp);
\\ You can also make up your own line ending characters:
\\ Read up to the first instance of ":"
stream_get_line($fp, 4096, ":");
This is a function I use to determine if a file contains Binary information. I use this for my search engine so that it doesn't try to index files like .zip or .mp3 or any other file that doesn't contain readable information. It makes use of the Character Type Extension if it's loaded, if it's not then it uses Regular Expressions.
function is_binary($link)
$tmpStr = '';
@$fp = fopen($link, 'rb');
@$tmpStr = fread($fp, 256);
@fclose($fp);
if($tmpStr != '')
$tmpStr = str_replace(chr(10), '', $tmpStr);
$tmpStr = str_replace(chr(13), '', $tmpStr);
a function based on "tunnelareaten at gmail dot com"s idea to search for files in a given directory by a searchstring or by fileextension.
I added support to search recursively through all sub-directories an to determine weather the filepath should be returned or not.
// recursive function to get contents of given folder by searchterm or fileextension
// (does not show folders)
// standards: Foldername: string
// Searchterm: string
// Searchtype: ext/search (file-extension or searchterm within filename)
// SaveCompletePath: true/1
// usage: array FileSearch_r($Folder,$Search[,$SearchType,$SavePath])
function FileSearch_r ( $Dir , $Search , $SearchType = "search" , $SavePath = 1 ) $Array =array();
$D = dir ( $Dir );
while ( false !==( $Entry = $D -> read ()))
if ( $Entry != '.' && $Entry != '..' ) $Entry = $Dir . $Entry ;
if ( is_dir ( $Entry )) $Array = array_merge ( $Array , FileSearch_r ( $Entry . '/' , $Search , $SearchType , $SavePath ));
else
if ( $SearchType == "search"
? substr_count ( $Entry , $Search )> 0
:( $SearchType == "ext"
? substr ( $Entry ,- strlen ( $Search ))=== $Search
: true ))
$Array []= $Entry ;
>
$D -> close ();
sort ( $Array , SORT_STRING );
if(!(bool) $SavePath ) $Array = str_replace ( $Dir , "" , array_values ( $Array ));
return $Array ;
>
?>
Here is a useful function if you're having trouble writing raw bytes into a file.
It receives an integer and returns an array containing the ASCII values of the bytes on each index of the array.
function int2bytes($number) $byte = $number;
$i=0;
do $dec_tmp = $byte;
$byte = bcdiv($byte,256,0);
$resto = $dec_tmp - (256 * $byte);
$return[] = $resto;
> while($byte >= 256);
if($byte) $return[] = $byte;
return array_reverse($return);
>
$arr will contain the following values:
Array
(
[0] => 1
[1] => 40
[2] => 56
)
Now, to write this data to the file, just use a fputs() with chr(), just like this:
На самом деле, чем открыть php файл, не является большой проблемой. Бывает труднее открыть бутылку пива, когда находишься посреди леса. Но так думают лишь заядлые программисты. А для новичков поведаем обо всех возможностях php для работы с файлами:
Чтение и запись файлов
Для простого отображения всего содержимого файла идеально подходит функция readfile () . Ее синтаксис:
readfile (string filename) , где string filename – строковое имя фала ( не дескриптор ).
Тот же самый файл можно прочитать с помощью функции fpassthru () . Она считывает данные от конечной позиции указателя и до конца файла. Ее синтаксис:
Для работы с функцией требуется открытие и закрытие файла. Пример:
Результат аналогичен предыдущему.
Функции для работы с файлами в php позволяют считывать содержимое построчно и посимвольно:
- string fgets ( int file, int length) – функция считывает строку длиною length . Пример:
- string fread (int file, int length) – по действию идентична предыдущей.
Для записи текстовых данных в файл существует две идентичные функции:
- int fputs ( int file, string string [, int length ])
- int fwrite ( int file, string string [, int length ])
Функции записывают в файл int file строку string string указанной длины int length ( необязательный аргумент ). Пример:
Переименование файлов с помощью функции PHP rename()
После прочтения с помощью php fread() файл можно переименовать файл или каталог, используя функцию PHP rename() , например:
Смотрите также
- is_readable() - Определяет существование файла и доступен ли он для чтения
- is_writable() - Определяет, доступен ли файл для записи
- is_file() - Определяет, является ли файл обычным файлом
- file() - Читает содержимое файла и помещает его в массив
- SplFileInfo
Примечания
Замечание: Результаты этой функции кешируются. Более подробную информацию смотрите в разделе clearstatcache() .
Начиная с PHP 5.0.0, эта функция также может быть использована с некоторыми обёртками url. Список обёрток, поддерживаемых семейством функций stat() , смотрите в разделе Поддерживаемые протоколы и обёртки.
Чтение всего содержимого файла
Функция fread() может использоваться в связке с функцией filesize() для полного считывания всего файла. filesize() возвращает размер файла в байтах. PHP fread пример:
Приведенный выше пример даст следующий результат:
Самый простой способ прочитать все содержимое файла - это функция readfile() . Она позволяет считать содержимое файла, не открывая его. Следующий пример даст тот же результат, что и предыдущий пример:
Приведенный выше пример даст следующий результат:
Другой способ прочитать все содержимое файла, не открывая его - это функция file_get_contents() . Она принимает имя и путь к файлу и считывает весь файл в строковую переменную. Пример без PHP fread :
Еще один способ считывания всех данных из файла - это функция file() . Она работает аналогично функции file_get_contents() , но возвращает содержимое как массив строк, а не одну строку. Каждый элемент возвращаемого массива соответствует строке в файле.
Чтобы обработать данные файла, необходимо выполнить обработку массива через цикл foreach . В следующем примере, мы считываем файл в массив и затем отображаем его с помощью цикла:
Примеры
if ( file_exists ( $filename )) echo "Файл $filename существует" ;
> else echo "Файл $filename не существует" ;
>
?>
Удаление файлов с помощью функции PHP unlink()
Можно удалять файлы или папки с помощью функции PHP unlink() , например:
Создание и удаление файлов
Чтобы создать файл php , можно использовать функцию fopen() в режиме доступа « w » или « w+ ». Или функцию touch () . Она устанавливает время изменения файла. При отсутствии элемента с искомым именем он будет создан. Ее синтаксис:
Для создания копии файла используется функция copy() . В качестве аргументов она принимает имя оригинала и файла, куда нужно скопировать содержимое. Если он не существует, то будет создан. Синтаксис функции:
Удалить файл можно с помощью функции unlink() . Ее синтаксис:
User Contributed Notes 31 notes
Note: The results of this function are cached. See clearstatcache() for more details.
That's a pretty big note. Don't forget this one, since it can make your file_exists() behave unexpectedly - probably at production time ;)
I needed to measure performance for a project, so I did a simple test with one million file_exists() and is_file() checks. In one scenario, only seven of the files existed. In the second, all files existed. is_file() needed 3.0 for scenario one and 3.3 seconds for scenario two. file_exists() needed 2.8 and 2.9 seconds, respectively. The absolute numbers are off course system-dependant, but it clearly indicates that file_exists() is faster.
Note that realpath() will return false if the file doesn't exist. So if you're going to absolutize the path and resolve symlinks anyway, you can just check the return value from realpath() instead of calling file_exists() first
In response to seejohnrun's version to check if a URL exists. Even if the file doesn't exist you're still going to get 404 headers. You can still use get_headers if you don't have the option of using CURL..
If you are trying to access a Windows Network Share you have to configure your WebServer with enough permissions for example:
You will get an error telling you that the pathname doesnt exist this will be because Apache or IIS run as LocalSystem so you will have to enter to Services and configure Apache on "Open a session as" Create a new user that has enough permissions and also be sure that target share has the proper permissions.
Hope this save some hours of research to anyone.
file_exists() does NOT search the php include_path for your file, so don't use it before trying to include or require.
@$result = include $filename;
Yes, include does return false when the file can't be found, but it does also generate a warning. That's why you need the @. Don't try to get around the warning issue by using file_exists(). That will leave you scratching your head until you figure out or stumble across the fact that file_exists() DOESN'T SEARCH THE PHP INCLUDE_PATH.
returns always "missing", even for an existing URL.
I found that in the same situation the file() function can read the remote file, so I changed my routine in
This is clearly a bit slower, especially if the remote file is big, but it solves this little problem.
For some reason, none of the url_exists() functions posted here worked for me, so here is my own tweaked version of it.
function url_exists ( $url ) $url = str_replace ( "http://" , "" , $url );
if ( strstr ( $url , "/" )) $url = explode ( "/" , $url , 2 );
$url [ 1 ] = "/" . $url [ 1 ];
> else $url = array( $url , "/" );
>
$fh = fsockopen ( $url [ 0 ], 80 );
if ( $fh ) fputs ( $fh , "GET " . $url [ 1 ]. " HTTP/1.1\nHost:" . $url [ 0 ]. "\n\n" );
if ( fread ( $fh , 22 ) == "HTTP/1.1 404 Not Found" ) < return FALSE ; >
else
If the file being tested by file_exists() is a file on a symbolically-linked directory structure, the results depend on the permissions of the directory tree node underneath the linked tree. PHP under a web server (i.e. apache) will respect permissions of the file system underneath the symbolic link, contrasting with PHP as a shell script which respects permissions of the directories that are linked (i.e. on top, and visible).
This results in files that appear to NOT exist on a symbolic link, even though they are very much in existance and indeed are readable by the web server.
When using file_exists, seems you cannot do:
foreach ( $possibles as $poss )
<
if ( file_exists ( SITE_RANGE_IMAGE_PATH . $this -> range_id . '/ ' . $poss . '.jpg' ) )
<
// exists
>
else
<
// not found
>
>
?>
so you must do:
foreach ( $possibles as $poss )
<
$img = SITE_RANGE_IMAGE_PATH . $this -> range_id . '/ ' . $poss . '.jpg'
if ( file_exists ( $img ) )
<
// exists
>
else
<
// not found
>
>
?>
Then things will work fine.
This is at least the case on this Windows system running php 5.2.5 and apache 2.2.3
Not sure if it is down to the concatenation or the fact theres a constant in there, i'm about to run away and test just that.
I wrote this little handy function to check if an image exists in a directory, and if so, return a filename which doesnt exists e.g. if you try 'flower.jpg' and it exists, then it tries 'flower[1].jpg' and if that one exists it tries 'flower[2].jpg' and so on. It works fine at my place. Ofcourse you can use it also for other filetypes than images.
function imageExists ( $image , $dir )
$i = 1 ; $probeer = $image ;
I was having problems with the file_exists when using urls, so I made this function:
function file_exists_2 ( $filePath )
return ( $ch = curl_init ( $filePath )) ? @ curl_close ( $ch ) || true : false ;
>
?>
Cheers!
this code here is in case you want to check if a file exists in another server:
function fileExists ( $path ) return (@ fopen ( $path , "r" )== true );
>
?>
unfortunately the file_exists can't reach remote servers, so I used the fopen function.
Here is a simpler version of url_exists:
Note on openspecies entry (excellent btw, thanks!).
If your server cannot resolve its own DNS, use the following:
$f = preg_replace('/www\.yourserver\.(net|com)/', getenv('SERVER_ADDR'), $f);
Just before the $h = @get_headers($f); line.
Replace the extensions (net|com|. ) in the regexp expression as appropriate.
Wordpress always prepends the full URL to any file it stores in its database so, as noted elsewhere, file_exists() can't find the file since it uses the 'document root', not the URL. An easy way out of this is to use:
file_exists (str_replace (home_url(), $_SERVER['DOCUMENT_ROOT'], $file) )
to check if file $file exists. Note: As from PHP8, 'DOCUMENT_ROOT' must be enclosed within SQUARE BRACKETS, not braces as suggested by ferodano at gmail dot com
I made a bit of code that sees whether a file served via RTSP is there or not:
function rtsp_exists ( $url )
$server = parse_url ( $url , PHP_URL_HOST );
$port = "554" ;
$hdrs = "DESCRIBE " . $url . " RTSP/1.0" . "\r\n\r\n" ;
//Open connection (15s timeout)
$sh = fsockopen ( $server , $port , $err , $err_otp , 15 );
//Check connections
if(! $sh ) return false ;
//Send headers
fputs ( $sh , $hdrs );
//Receive data (1KB)
$rtds = fgets ( $sh , 1024 );
//Close socket
fclose ( $sh );
return strpos ( $rtds , "200 OK" ) > 0 ;
>
?>
NB: This function expects the full server-related pathname to work.
For example, if you run a PHP routine from within, for example, the root folder of your website and and ask:
You will get FALSE even if that file does exist off root.
You need to add
Older php (v4.x) do not work with get_headers() function. So I made this one and working.
function url_exists ( $url ) // Version 4.x supported
$handle = curl_init ( $url );
if ( false === $handle )
return false ;
>
curl_setopt ( $handle , CURLOPT_HEADER , false );
curl_setopt ( $handle , CURLOPT_FAILONERROR , true ); // this works
curl_setopt ( $handle , CURLOPT_NOBODY , true );
curl_setopt ( $handle , CURLOPT_RETURNTRANSFER , false );
$connectable = curl_exec ( $handle );
curl_close ( $handle );
return $connectable ;
>
?>
You could use document root to be on the safer side because the function does not take relative paths:
if( file_exists ( $_SERVER < 'DOCUMENT_ROOT' >. "/my_images/abc.jpg" )) <
.
>
?>
Do not forget to put the slash '/', e.g. my doc root in Ubuntu is /var/www without the slash.
file_exists will have trouble finding your file if the file permissions are not read enabled for 'other' when not owned by your php user. I thought I was having trouble with a directory name having a space in it (/users/andrew/Pictures/iPhoto Library/AlbumData.xml) but the reality was that there weren't read permissions on Pictures, iPhoto Library or AlbumData.xml. Once I fixed that, file_exists worked.
I spent the last two hours wondering what was wrong with my if statement: file_exists($file) was returning false, however I could call include($file) with no problem.
It turns out that I didn't realize that the php include_path value I had set in the .htaccess file didn't carry over to file_exists, is_file, etc.
// .htaccess php_value include_path '/home/user/public_html/';
// includes lies in /home/user/public_html/includes/
//doesn't work, file_exists returns false
if ( file_exists ( 'includes/config.php' ) )
include( 'includes/config.php' );
>
//does work, file_exists returns true
if ( file_exists ( '/home/user/public_html/includes/config.php' ) )
include( 'includes/config.php' );
>
?>
Just goes to show that "shortcuts for simplicity" like setting the include_path in .htaccess can just cause more grief in the long run.
file_exists() will return FALSE for broken links
$ ln -s does_not_exist my_link
$ ls -l
lrwxr-xr-x 1 user group 14 May 13 17:28 my_link -> does_not_exist
$ php -r "var_dump(file_exists('my_link'));"
bool(false)
The code can be used to t a filename that can be used to create a new filename.
function generateRandomString ( $length = 8 )
<
$string = "" ;
//character that can be used
$possible = "0123456789bcdfghjkmnpqrstvwxyz" ;
for( $i = 0 ; $i < $length ; $i ++)
<
$char = substr ( $possible , rand ( 0 , strlen ( $possible )- 1 ), 1 );
if (! strstr ( $string , $char ))
<
$string .= $char ;
>
>
function randomFile ( $folder = '' , $extension = '' )
<
$folder = trim ( $folder );
$folder = ( $folder == '' ) ? './' : $folder ;
//check if directory exist
if (! is_dir ( $folder ))
//generate a filepath
$filepath = $folder . "/" . generateRandomString ( 128 ) . $extension ;
//check if that filepath already exist, if it exist if generates again
//till if gets one that doesn't exist
while( file_exists ( $filepath ))
<
$filepath = $folder . "/" . generateRandomString ( 128 ) . $extension ;
>
The following script checks if there is a file with the same name and adds _n to the end of the file name, where n increases. if img.jpg is on the server, it tries with img_0.jpg, checks if it is on the server and tries with img_1.jpg.
$img = "images/" . $_FILES [ 'bilde' ][ 'name' ];
$t = 0 ;
while( file_exists ( $img )) $img = "images/" . $_FILES [ 'bilde' ][ 'name' ];
$img = substr ( $img , 0 , strpos ( $img , "." )). "_ $t " . strstr ( $img , "." );
$t ++;
>
move_uploaded_file ( $_FILES [ 'bilde' ][ 'tmp_name' ], $img );
?>
My way of making sure files exist before including them is as follows (example: including a class file in an autoloader):
function __autoload ( $name )
<
$path = explode ( ":" , ini_get ( 'include_path' )); //get all the possible paths to the file (preloaded with the file structure of the project)
foreach( $path as $tryThis )
<
//try each possible iteration of the file name and use the first one that comes up
// name.class.php first
$exists = file_exists ( $tryThis . '/' . $name . '.class.php' );
if ( $exists )
<
include_once( $name . '.class.php' );
return;
>
//ok that didn't work, try the other way around
$exists = file_exists ( $tryThis . '/' . 'class.' . $name . '.php' );
if ( $exists )
<
include_once( 'class.' . $name . '.php' );
return;
>
//neither did that. let's try as an inc.php
$exists = file_exists ( $tryThis . '/' . $name . '.inc.php' );
if ( $exists )
<
include_once( $name . '.inc.php' );
return;
>
>
// can't find it.
die( "Class $name could not be found!" );
>
?>
If checking for a file newly created by an external program in Windows then file_exists() does not recognize it immediately. Iy seems that a short timeout may be required.
$file = 'file.tmp';
if ($h = popen("start \"bla\" touch $file", "r")) pclose($h);
// now I would like know if a file was created
// note: usleep not supported
$start = gettimeofday();
while (!file_exists(trim($file, " '\""))) $stop = gettimeofday();
if ( 1000000 * ($stop['sec'] - $start['sec']) + $stop['usec'] - $start['usec'] > 500000) break; // wait a moment
>
if (file_exists($file)) // now should be reliable
?>
file_exists() is vulnerable to race conditions and clearstatcache() is not adequate to avoid it.
The following function is a good solution:
function file_exists_safe ( $file ) if (! $fd = fopen ( $file , 'xb' )) return true ; // the file already exists
>
fclose ( $fd ); // the file is now created, we don't need the file handler
return false ;
>
?>
The function will create a file if non-existent, following calls will fail because the file exists (in effect being a lock).
IMPORTANT: The file will remain on the disk if it was successfully created and you must clean up after you, f.ex. remove it or overwrite it. This step is purposely omitted from the function as to let scripts do calculations all the while being sure the file won't be "seized" by another process.
function create_and_lock ( $file ) if (! $fd = fopen ( $file , 'xb' )) return false ;
>
if (! flock ( $fd , LOCK_EX | LOCK_NB )) < // may fail for other reasons, LOCK_NB will prevent blocking
fclose ( $fd );
unlink ( $file ); // clean up
return false ;
>
return $fd ;
>
Если вы хотите, чтобы использовался поиск файла в include_path, установите этот параметр в true .
Файлы php
Файлы с расширением php содержат в себе код написанный, на одноименном языке программирования. В отличие от других языков, php является серверным языком программирования. То есть он выполняется на стороне сервера. Поэтому для отладки его кода на клиентской машине должен быть установлен локальный сервер.
Для работы с файлами php используются специальные приложения – программные редакторы. Наиболее распространенными из них являются:
- Dreamweaver.
- PHPEdit.
- Eclipse PHP Development.
При создании сайтов на основе php может потребоваться многократное использование программного кода. В таких ситуациях удобно подключать уже готовые решения, находящиеся в другом файле. Для этого используется конструкция include . Ее синтаксис:
Чтение фиксированного количества символов
Функция PHP fread() может использоваться для чтения заданного количества символов из файла. Базовый синтаксис функции:
Она принимает два параметра - дескриптор файла и количество байтов, которые должны быть считаны. В следующем примере мы считываем 20 байтов из файла data.txt , включая пробелы. Предположим, data.txt содержит абзац текста " The quick brown fox jumps over the lazy dog ":
Приведенный выше пример даст следующий результат:
Открытие и закрытие файлов
В php все операции с файлами осуществляются в несколько этапов:
- Открытие файла;
- Редактирование содержимого;
- Закрытие файла.
Для открытия файла используется функция fopen() . Ее синтаксис:
- string mode – указывает режим открытия файла. Принимаемые аргументом значения:
- r – файл открыт только для чтения, файловый указатель устанавливается в начале;
- r+ – файл открыт для чтения и записи;
- w – создается новый файл только для записи. Если файл с таким именем уже существует, в нем происходит автоматическое удаление всех данных;
- w+ - создается новый файл для записи и чтения. При существовании такого файла происходит полная перезапись его данных на новые;
- a – файл открыт для записи. Указатель устанавливается в конце. То есть запись в файл php начнется не с начала, а с конца;
- a+ – открытие файла в режиме чтения и записи. Запись начнется с конца;
- b – режим работы с файлом, содержащим в себе двоичные данные (в двоичной системе исчисления). Этот режим доступен только в операционной системе Windows.
Для закрытия доступа к файлу служит функция fclose () . Синтаксис:
int fclose (int file) , где int file – дескриптор сайта, который нужно закрыть.
После каждого чтения или записи файл нужно закрывать этой функцией. Иначе остается открытым поток, созданный для файла. А это ведет к лишнему расходу серверных мощностей.
Ошибки
В случае неудачного завершения работы генерируется ошибка уровня E_WARNING .
Получение информации о файле
Для получения информации о файлах в php используется целый ряд функций:
- bool fileexists (string filename) – проверяет, существует ли элемент;
- int fileatime (string filename) – возвращает время последнего открытия;
- int filesize (string filename) – возвращает байтовый размер файла;
- string filetype (string filename) – тип файла.
Это еще не все возможности для работы с файлами, реализованные в php . Многие из методов и функций остались за кадром. Так что простор для самостоятельного познания еще велик.
Возвращаемые значения
Возвращает количество прочитанных из файла байт в случае успешного выполнения или false в случае возникновения ошибки
Читайте также: