Размер файла на WEB сервере.

Как узнать размер файла, находящегося на web сервере, если есть прямая ссылка на файл ?
В директории отключена опция:

Options -Indexes

т.е. список нельзя получить и оттуда выковыривать размер файла.

В общем случае

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

Кстати, обратите внимание, что есть такая штука, mod_rewrite, который позволяет "спрятать" скрипт, чтобы извне он был виден как статический файл (то есть если URL выглядит как статический, это ничего не означает).

Но если речь идет точно о статических файлах, то обычно сервер пишет размер файла и прочую информацию (например, дата последнего обновления) в заголовке ответа (строчка content-length; можно просто отключиться от сервера после получения заголовков), плюс часть серверов реализует специальный запрос HTTP HEAD, который возвращает только заголовки, но не возвращает сами данные.

Quote: если речь

Quote:
если речь идет точно о статических файлах
Точно статические.

Quote:
плюс часть серверов реализует специальный запрос HTTP HEAD, который возвращает только заголовки, но не возвращает сами данные.
HEAD не поддерживает, вот ответ на запрос:

<HTML>
<HEAD><TITLE>An Error Occurred</TITLE></HEAD>
<BODY>
<H1>An Error Occurred</H1>
405 Method Not Allowed
</BODY>
</HTML>

Как быть в таком случае ?

Для такого

Для такого случая не могу предложить ничего лучше чем сделать свою спец-реализацию HTTP GET, которая будет отваливаться сразу после получения хидеров..
В принципе ничего особенного, наверное проще всего LWP хакнуть переопределением встроенной функции. Я даже где-то встречал пример, кажется на perlmonks, так достигали ограничение скорости скачивания файла.

Вобщем нужно переопределить функцию sysread, чтобы она по получению достаточного числа строчек шапки закрывала соединение :)

Переопределение функции делается примерно так:

*grow = \&expand;
sub expand
{
  # делаем чего хотим
  #
  #
  # вызываем встроенную функцию и возвращаем ее ответ
  return CORE::grow(@_);
}

Ниасилил твой

Ниасилил твой пост =)

Дай кусок кода,

Дай кусок кода, которым смотришь размер, я его модифицирую как надо.

В том то и дело

В том то и дело что кода как такового нет, вот ламерский вариант:

use LWP::Simple;
sub get_signature_size
{
	my $sig_name = shift;
	my $download_file = "http://10.10.1.10:2221/$sig_name";
	my $data = get($download_file);
	die "Download error!\n" unless defined($data);
	return length($data);
}

Нашел модуль,

Нашел модуль, HTTP::Size. Только вот он через cpan не ставится =(

------------------

#!/usr/bin/perl
print("подпись!!1\n");

Извини, у меня

Извини, у меня просто целая полоса неудач- сломался ноут, на котором я работал, ремонт затянулся, тут похолодание и я заболел, поэтому никак не соберусь написать..
Скелет кода уже готов, но надо немножко поэкспериментировать с подменой sysread - там даже с первого взгляда есть нюансы, а я хочу еще и изнутри подменяющей функции сокет закрывать :)

Это конечно не

Это конечно не мое дело, но может быть стоит в таком случае уже обойтись
IO::Socket и ручной обработкой заголовка Content-length, если сервер все же отдает его,
и рвать соединение руками?

У меня валялась болванка чего-то подобного, если нужно.
Если нужен только размер файла, то весь LWP ни к чему, имхо...

UPD: вот, откопал

use IO::Socket;
use Time::HiRes qw/time/;
my $time = time;
my $host = 'kiev.pm.org';
my $sock = IO::Socket::INET->new(PeerAddr => $host,
                                 PeerPort => 'http(80)',
                                 Proto    => 'tcp');
my $file = '/files/pictures/picture-251.gif';
 
if ($sock) {
 Log("Connected");
} else {
 Log("Can not make connection to '${host}': $!");
 exit;
}
 
print $sock "GET ${file} HTTP/1.1\r\nHost: ${host}\r\nUser-Agent: Dummy Perl client\r\nConnection: close\r\n\r\n";
Log("Requested file ${file} from http://${host}");
my $buff;
 
my $ch;
my $line;
while($sock->read($ch,1)) {
 if ($ch eq "\n") {
  if ($line =~ /^[\r\n]{0,1}$/) { last; }
  if ($line =~ /HTTP\/\d+.\d+ (\d+) (.*?)\r{0,1}$/) {
   unless ($1 == 200)  {
    Log("Server returned ${1}: '${2}' on file ${file}");
    $sock->close();
    last;
   }
  }
  Log($line);
  if ($line =~ /^Content-Length: (\d+)\r{0,1}/) {
   print "\n\nFile '${file}': $1 bytes\n";
    $sock->close();
    last;
  }
  $line = '';
 } else { $line .= $ch; }
}
print "Done.\n";
 
sub Log {
 my $string = shift;
 my $ltm =(time - $time);
 $ltm = substr($ltm,0,7);
 print "[" . $ltm . (" " x (8-length($ltm))) . "]: $string\n";
}

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

LWP портабельней

LWP портабельней - при подмене sysread в самом худшем случае просто не будет работать "хитрое" определение размера, и кроме всего прозрачно переключается на работу с прокси, что есть полезно.
И в целом у меня получается размер кода эквивалентный.

согласен

согласен