Глава 39. Работа с удаленными файлами

В случае, если опция allow_url_fopen включена в конфигурационном файле php.ini, вы можете использовать HTTP и FTP ссылки в большинстве функций, принимающих в качестве параметра имя файла. Также вы можете использовать ссылки в операторах include(), include_once(), require() и require_once(). Дополнительную информацию о поддерживаемых в PHP протоколах вы можете найти в Прил. M.

Замечание: В 4.0.3 и более ранних версиях при сборке необходимо использовать опцию --enable-url-fopen-wrapper для активации возможности работать с удаленными файлами.

Замечание: Дистрибутивы PHP для Windows-платформ до версии 4.3 не поддерживают возможности работы с удаленными файлами для следующих операторов: include(), include_once(), require(), require_once(), и функций вида imagecreatefromXXX (Ссылка LVII, Image Functions).

Например, вы можете использовать это для того, чтобы открыть файл на удаленном сервере, извлечь необходимые вам данные и использовать их в запросе к базе данных или же просто отобразить их в дизайне вашего сайта.

Пример 39-1. Получение заголовка удаленной страницы

<?php
$file
= fopen ("http://www.example.com/", "r");
if (!
$file) {
   echo
"<p>Unable to open remote file.\n";
   exit;
}
while (!
feof ($file)) {
  
$line = fgets ($file, 1024);
  
/* Сработает, только если заголовок и сопутствующие теги расположены в одной строке */
  
if (eregi ("<title>(.*)</title>", $line, $out)) {
      
$title = $out[1];
       break;
   }
}
fclose($file);
?>

Вы также можете работать с удаленными файлами, расположенными на FTP-сервере (подразумевается, что вы авторизировались с необходимыми для этого привилегиями). Таким образом вы можете создавать новые файлы, но попытка перезаписать существующий файл при помощи функции fopen() приведет к ошибке.

Для того, что бы авторизироваться под пользователем, отличным от 'anonymous', вам необходимо указать логин (и, возможно, пароль) в адресной строке, например так: 'ftp://user:password@ftp.example.com/path/to/file'. (Вы можете использовать этот же синтаксис для доступа к удаленным файлам по HTTP-протоколу, если необходима Basic-авторизация.)

Пример 39-2. Сохранение данных на удаленном сервере

<?php
$file
= fopen ("ftp://ftp.example.com/incoming/outputfile", "w");
if (!
$file) {
   echo
"<p>Unable to open remote file for writing.\n";
   exit;
}
/* Запись данных. */
fputs ($file, $_SERVER['HTTP_USER_AGENT'] . "\n");
fclose ($file);
?>

Замечание: Глядя на приведенный выше пример, у вас может возникнуть идея использовать эту технику для ведения удаленного лог-файла. К сожалению, это не реализуемо, поскольку попытка записи в уже существующий удаленный файл при помощи функции fopen() приведет к ошибке. В реализации распределенного логирования, возможно, вам поможет функция syslog().



Работа с удаленными файлами
geoffrey at nevra dot net
06-May-2006 03:53
Really, you should not send headers terminated by \n - it's not per-rfc supported by a HTTP server.

Instead, send as \r\n which is what the protocol specifies, and that regular expression would be matched anywhere, so match for something like /^Content-Length: \d+$/i on each header-line (headers are terminated by the regular expression  /(\r\n|[\r\n])/ - so preg_split on that. Remeber to use the appropriate flags, I can't be arsed to look them up)
heck at fas dot harvard dot edu
14-Sep-2004 12:06
The previous post is part right, part wrong. It's part right because it's true that the php script will run on the remote server, if it's capable of interpreting php scripts. You can see this by creating this script on a remote machine:
<?php
echo system("hostname");
?>
Then include that in a php file on your local machine. When you view it in a browser, you'll see the hostname of the remote machine.

However, that does not mean there are no security worries here. Just try replacing the previous script with this one:
<?php
echo "<?php system(\"hostname\"); ?>";
?>
I'm guessing you can figure out what that's gonna do.

So yes, remote includes can be a major security problem.
geoffrey at nevra dot net
04-Aug-2003 05:25
ok, here is the story:

I was trying to download remote images, finding urls throught apache indexs with regexps and fopen()ing them to get the datas. It didn't work. I thought about binary considerations. Putting the 'b' in the second argument of fopen didn't help much, my browser still didn't want to display the images. I finally understood by watching the datas i was getting from the remote host: it was an html page ! hey, i didn't know apache sent html pages when requesting images, did you ?
the right way is then to send an http request via fsockopen. Here comes my second problem, using explode("\n\n", $buffer); to get rid of the headers. The right way is to get the value of the Content-Lenght field and use it in substr($buffer, -$Content-Lenght);

finally, here is my own function to download these files:

<?php
function http_get($url)
{

  
$url_stuff = parse_url($url);
  
$port = isset($url_stuff['port']) ? $url_stuff['port'] : 80;

  
$fp = fsockopen($url_stuff['host'], $port);

  
$query  = 'GET ' . $url_stuff['path'] . " HTTP/1.0\n";
  
$query .= 'Host: ' . $url_stuff['host'];
  
$query .= "\n\n";

  
fwrite($fp, $query);

   while (
$tmp = fread($fp, 1024))
   {
      
$buffer .= $tmp;
   }

  
preg_match('/Content-Length: ([0-9]+)/', $buffer, $parts);
   return
substr($buffer, - $parts[1]);
?>

}

ho, maybe you'll say i could have parsed the page to get rid of the html stuff, but i wanted to experience http a little ;)

<Поддержка метода PUTРабота с соединениями>
 Last updated: Tue, 15 Nov 2005