LINUX.ORG.RU

На сервер загружается файл большего размера чем изначальный

 , ,


0

1

На сервере: debian stable 6 + ngnix + perl + fastcgi:

use CGI::Fast;
#...
while(my $cgi = CGI::Fast->new()) {
#...
	if(!defined($cgi->param('file'))){
		print <<"T";
<html>
<head>
<body>
<form method="post" action="/x/" enctype="multipart/form-data">
<input type="file" name="file"><br>
<input type="submit" name="button" value="Ok">
</form>
</body>
</html>
T
	}
	else{
		my $name = $cgi->param('file');
		my $fh = $cgi->upload('file');
		my $size = 0;
		my $buffer;
 		open(my $f, ">$DIRNAME/$name") or $!;
		while (my $c = read($fh,$buffer,16384)) {
			$size += $c;
			print $f $buffer;
		}
		close($f);
		print <<"T";
<html>
<head>
<body>
OK. FileName: $name, FileSize: $size
</body>
</html>
T
#...
}

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

Я заметил, что это происходит с бинарным файлом, с текстовым нет, хотя для linux на сколько я знаю разницы нет. Как исправить? Что не верно в коде?

★★★

Разобрался. Оказывается у меня в начале файла было определено:

use open ':encoding(utf8)';

Заменил

open(my $f, ">$DIRNAME/$name") or $!; 
на
open(my $f, ">:bytes","$DIRNAME/$name") or $!; 
Теперь файл такого же размера как и изначальный

Mrak ★★★ ()
Последнее исправление: Mrak (всего исправлений: 2)

Что если read и print заменить соответственно на sysread и syswrite?

Olegymous ★★ ()
Ответ на: комментарий от Mrak

Да, в таком случае read и print в отличии от syread и syswrite оперируют символами, а не байтами.

Olegymous ★★ ()
Ответ на: комментарий от Mrak

Кстати, что за странная операция

or $!;
Обычно пишут
or die $!;

Olegymous ★★ ()
Ответ на: комментарий от Olegymous

Да, в таком случае read и print в отличии от syread и syswrite оперируют символами, а не байтами.

Вы считаете, что лучше переписать код записи файлов на sys* функции?

Кстати, что за странная операция

Согласен, спасибо - fixed

Mrak ★★★ ()
Ответ на: комментарий от Mrak

Думаю это не принципиально, хотя sys* функции были бы, возможно, чуть эффективнее.

Olegymous ★★ ()
Ответ на: комментарий от Mrak

Вы считаете, что лучше переписать код записи файлов на sys* функции?

Лучше переписать на sys*. У функции print есть такие фичи как например буфер. Попробуй запустить:

#!/usr/bin/perl
print "1";
syswrite STDOUT, "2";
print "3";
и сам все поймещь.

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

По поводу die, у тебя же fastCGI, он должен пахать в цикле 24 на 7. В таком случае лучше не делать точки завершения программы, сделай что бы он ошибки в лог файл писал.

TDrive ★★★★★ ()
Последнее исправление: TDrive (всего исправлений: 1)
Ответ на: комментарий от TDrive

да и буфер этот можно отключить

Да все верно если объявить переменную $|=1, то проблем с буферизацией не должно быть

По поводу die, у тебя же fastCGI

Так и делаю, спасибо

Mrak ★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.