Контроль скачивания файлов

litvinenko

Новичок
Контроль скачивания файлов

Доброго времени суток всем!
Помогите люди добрые.
Начальство поставило такую вот, на мой взгляд, бесполезную, но ОЧЕНЬ хЫтрую задачу. Вот ее полный текст:

"нужен скрипт.

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

Помогите, плз. С самой закачкой проблем нет. Но вот, как отследить, докачался ли файл полностью, ничего ли не произошло плохого во время скачивания - это у меня не получается отследить.
 
Какой размер файла? Может отдавать файл в цикле кусками и проверять connection_aborted?
 

_vampiro_

Новичок
а если я регетом качаю в 5 потоков....? як быть?
:)
поле для ввода:

пожалуйста, введите последние 5 байт скачанного файла [..]
 

litvinenko

Новичок
значит у меня вот как получается:
в начале скрипта открывается еще одно, где при помощи header происходит закачка файла и одновременная запись в файл count.txt число скачаных байт.
в основном же окне проверяется размер файла count.txt.
если размер становится больше нуля, то смотрим, какое число там записано, если оно размеру файла, который скачивали, значит все впорядке, если число другое - что-то произошло. У меня правильный ход мысли?
вот еще вопрос, м.б. он покажется глупым, но все же: размер пустого файла равен нулю?
 
_vampiro_ Если файл выгружается через скрипт, который не поддерживает seek, ты не сможешь создать 2 потока, так как в заголовке второго тебе сказут изначальный range 0-end и твой загрузчик должен сказать что потоки не поддерживаются
 

litvinenko

Новичок
файл 1.php
-------------------
<?php
$countfile = "tmp/count.txt";
$f = fopen($countfile,"w+");
if($f)
{
fwrite($f,"");
fclose($f);
}

//file, kotoriy kopiruem
$file = "12.zip";

//otkrivaem okno, gde budet ska4ivanie
echo "<script>window.open(\"2.php?file=".$file."\");</script>";
flush();

//poka razmer faila = 0 spim po 1 sekunde
$i = 0;
while(filesize($countfile)==0)
{
echo $i;
flush();
sleep(1);
}

$size = file($countfile);
if($size[0]==filesize($file))
{
echo "<script>alert('ok');</script>";
}
else
{
echo "<script>alert('ne ok');</script>";
}
?>
-------------------
файл 2.php:

<?php
$file = $_GET['file'];
ignore_user_abort(false);

header('Content-Type: application/octet-stream;');
header('Content-Disposition: attachment; filename="'.$file.'"');
$contents = '';

define('FILE_PART_SIZE',8192);
$c = readfile($file);
$h2 = fopen("tmp/count.txt", "w+");
fwrite($h2,$c);
fclose($h2);
flush();
fclose($h);
?>

скачивание работает нормально. а вот с контролем что-то не так. но я точно знаю, что должно быть примерно так :)
 
litvinenko
В 1.php в цикле нужен clearstatcache, иначе будет размер кешироваться
 

_vampiro_

Новичок
Returns the number of bytes read from the file. If an error occurs, FALSE is returned and unless the function was called as @readfile(), an error message is printed.

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

-~{}~ 20.06.06 17:03:

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

litvinenko

Новичок
можно читать через fread($h, FILE_PART_SIZE);
но ведь в конце файла, может прочитаться не FILE_PART_SIZE, а меньше... как это отследить?

-~{}~ 20.06.06 17:09:

shtogrin, спасибо. Действительно помогла эта функция.
остальсь только файл забирать по кускам, отслеживая, сколько забрал.
а вот еще вопрос попутно.
как-нить можно потом програмно закрыть окно 2.php?
 

_vampiro_

Новичок
а зачем следить? пусть меньше. Плюсуем это к уже выданному. И если (сумма ==размер файла) -значит все "ок" и можно кидать "зеленый флаг" скрипту №1.
 

Turist

Новичок
Были подобные темы.
Я даже как-то писал скрипт в помощь ;) Вот тут лежит:
http://onlyforread.livejournal.com/11715.html#cutid1
Обратите внимание на function shdn()
 

litvinenko

Новичок
пробовал я этот скрипт.
у меня почему-то не выполнялась функция shdn()
после header вообще ничего не хотело делаться.
 

Turist

Новичок
litvinenko Вы обратили внимание на фразу: ... В скрипте есть некоторые недочёты ... . Если вы в нём разобрались и их устранили, то не работать может только из-за настроек PHP (в чём я очень самневаюсь)
 

litvinenko

Новичок
этот кусок кода проверяет, изменяется ли размер файла или нет:

while(filesize($countfile)==0)
{
clearstatcache();
flush();
sleep(1);
$i++;
echo $i;
if($i>20)
{
unlink($countfile);
return "<script>alert('слишком долго!');</script>";
}
}

но он почему-то не работает. Подскажите, плз, что здесь неправильно?
 
Тебе даже не размер нужем а содержимое или даже наличие файла. И имя файла должно быть уникальное для запроса, так что бы могли грузится два файла.
 

litvinenko

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

-~{}~ 22.06.06 15:12:

1.php
***********************************
<?php

function download($file)
{

function content($file)
{
$f = fopen($file,'rb');
flock($f,2);
$size = fread($f,filesize($file));
flock($f,3);
return $size;
}

getallheaders();

//sozdaem i ostavlyaem pustim file s logom
$countfile = "tmp/count.txt";
if(file_exists($countfile))
{
unlink($countfile);
}

$f = fopen($countfile,"w");
if($f)
{
fwrite($f,"0");
fclose($f);
}
else
{
return "<script>alert('ne mogu otkrit file');</script>";
}

//otkrivaem okno, gde budet ska4ivanie
echo "<script>window.open(\"2.php?file=".$file."\");</script>";
flush();

$i = 0;
$re = 0;

$flag = true;
while($flag)
{
sleep(1);
flush();
$oldsize = content($countfile);
clearstatcache();
$newsize = content($countfile);

if($newsize==0)
{
$re++;
if($re==8)
{
$flag = false;
return "ne ok";
}
}
else
{
if($newsize >= filesize($file))
{
$flag = false;
return "ok";
}
else
{
$re++;
if($oldsize == $newsize)
{
if($re==8)
{
$flag = false;
return "ne ok";
}
}
}
}
}
}

echo download("12.zip");
?>

-~{}~ 22.06.06 15:13:

2.php
********************************************
<?php
$file = $_GET['file'];
ignore_user_abort(false);

header('Content-Type: application/octet-stream;');
header('Content-Disposition: attachment; filename="'.$file.'"');
$contents = '';


$file_part_size = 8192;
$g_total = 0;
$handle = fopen($file,"rb");
if($handle)
{
while(!feof($handle))
{
$h2 = fopen("tmp/count.txt", "wb");
// flock($h2,1);
fwrite($h2,$g_total);
// flock($h2,3);
fclose($h2);

if(!feof($handle))
{
$g_total += $file_part_size;
echo fread($handle,$file_part_size);
flush();


if((filesize($file)-$g_total < $file_part_size) and (filesize($file)!=$g_total))
{
$file_part_size = filesize($file) - $g_total;
}
}

}
}
?>

-~{}~ 22.06.06 15:14:

так же могут возникнуть проблемы при частом скачивании.
но все же думаю, код будет полезен.
 
Сверху