Учёт объёма скачанной информации авторизованным пользователем.

  • Автор темы da_andy
  • Дата начала

da_andy

Guest
Учёт объёма скачанной информации авторизованным пользователем.

Как возомжно вести учёт объёма скачанной информации авторизованным пользователем?

Т.е. например на сайте лежат несколько гиг файлов, нужно чтобы пользователь мог скачать не больше одного гига.
Как это вообще можно реализовать на PHP? Пожалуйста, подскажите где копать.
 

DimbIch

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

gromitus

Новичок
помойму можно что то установить, что бы сервер поддерживал докачку. И сказать клиентам, что бы они пользовались тоьлко программами поддерживающими докачку. Помойму такие и бесплатные есть.
А потом - дело техники.
 

da_andy

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

desperado

Новичок
можо линковать файлы, а не копировать.

но тогда придется парсить логи и считать кто и сколько раз скачал этот файл.

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

agx

Программер :-)
А может задействовать БД?
Пользователь начинает качать файл - помещать его идентификатор в БД. И прибавлять объем файла к траффику.
Если файл не докачался - ничего страшного, пользователь попытается скачать файл еще раз, и если идентификатор уже есть в БД, траффик не увеличится.
В общем, это то же самое, что с отдельной папкой, но только проще.
 

neko

tеam neko
если будете и дальше столько пить, бидэ задействовать придется непременно

во-первых это 2 разные задачи:
Как возомжно вести учёт объёма скачанной информации авторизованным пользователем?
директория с именем клиента, в которую доступ етсть только у него и выбранные файлы, если они не превышают объёма копируются в эту папку.
это не мешает их скачать 50 раз и раздать ссылки, если что

во-вторых нельзя узнать сколько реально скачано, можно только узнать сколько сервер отдал

делать можно так:
а. выдавать файлы пыхом, и там ручками считать
б. обрабатывать логи апача
в. повесить apache_hook
 

che

Guest
Originally posted by neko


делать можно так:
а. выдавать файлы пыхом, и там ручками считать
Каким макаром? Отдали файло в гектар и записали что гектор скачан? Я сейчас над тем же бьюсь и если ты мне обьяснишь как это сделать то буду сильно благодарен.
Пока что я отдаю небольшими кусками и connection close, если запрошен по новой но уже со смещением, значит предыдущий был скачан. но беда в том что бродилки (по крайней мере опера) это не воспринимают и удовлетворяются первым куском, а wget к примеру останавливается после 20 попыток если не указать иное. То есть что? просить юзерей персонально настраивать менеджеры? Не вариант.
Кроме того, регет к примеру не хочет заводить несколько потоков, качает упрямо в один. Не то что бы меня это смущало, но интересно же почему. Код на всякий случай здесь:
PHP:
<?php   
 download ($_GET['file'], 50*1024);    
function  download($file, $portion)	{  
$length=filesize($file);  
$h = fopen($file, 'rb');    		
         header ('HTTP/1.1 206 Partial Content');
 	header ('Content-Disposition: attachment; filename='.$file); 
         header ('Accept-Ranges: bytes');    	
if (isset($_SERVER['HTTP_RANGE'])) {    		
    $arr=array();  		
    ereg('[1-9][0-9]*', $_SERVER['HTTP_RANGE'], $arr);  
    offs=(int)$arr[0];  		
    fseek ( $h, $offs);  		
    $content=fread($h, $portion);  		
        header ('Content-Length: '.($length-$offs));  		
        header ('Content-Range: bytes '.$arr[0].'-'.($length-1).'/'.$length);    	
}  	
else {  		
    $content=fread($h, $portion);  		
        header ('Content-Length: '.$length);  		
        header ('Content-Range: bytes 0-'.($length-1).'/'.$length);  	
}    		
        header ('Content-type: application/octet-stream');  		
        header ('Connection: close');  		
    echo $content;  		
    fclose ($h);    		
}  
?>
 

neko

tеam neko
che
как выдавать файлы и обрабатывать range на форуме примеров масса
а дальше ты выдаешь этот свой кусок -- бери и плюсуй к "траффиковому счету" пользователя

если ты выдаешь файлы сам -- посчитать никакой проблемы нет
если есть проблема их выдавать правильно -- в поиск

-~{}~ 02.11.04 05:07:

*content-range*
 

che

Guest
Originally posted by neko
che
если есть проблема их выдавать правильно -- в поиск
Искал. В том числе и только что.
Проблема в том что в основном обсуждается как организовать докачку, а меня волнует как отдавая на запрос всего файла (или остатка начиная со смещения x) такой кусок, какой я посчитаю нужным, объяснить это в хидерах клиенту, закрыть соединение и чтобы это не стало неожиданностью для клиента. То есть просит он последние 50 килобайт, отдаю я ему 30 и клиент понимает что это тридцать, что больше в ЭТОМ соединении я передавать ничего не собирался и что закрытие соединения это по сценарию. Регет пишет Сервер неожиданно закрыл соединение. Что надо сделать чтобы закрытие не было неожиданностью и не воспринималась как ошибка?

Эээ... Погорячился. Как объяснить клиенту, что его запрос выполнен и кина больше не будет. Если хочет еще, то пусть шлет следующий. Если для этого не надо закрывать соединение, то будет здорово.
 

desperado

Новичок
ну а что ты от регета хочешь? он попросил у тебя 50 кубиков, а ты ему вместо слов - нет у меня 50-ти кубиков, выдаешь ему 30 кубиков. что думать регету? правильно - его кинули.

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

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

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

neko

tеam neko
это, скажем так, не предусмотрено протоколом

Эээ... Погорячился. Как объяснить клиенту, что его запрос выполнен и кина больше не будет. Если хочет еще, то пусть шлет следующий.
клиенты о которых ты говорил они как раз правильно все делают (читай по протоколу)
и врядли станут действовать иначе
неправильно делаешь ты
 

che

Guest
С Неко я согласен. Причем согласен был до поста, просто тлела еще надежда. А Десперадой будем общаться.
ну и как было сказано - тут все это было пережевано + в мане в комментах был почти 100% рабочий пример, как отдовать файло с докачкой, туда надо лишь (в месте от-дования) впихнуть подсчет отданного и запись его в нужное место.
Ты в суть проблемы вникнуть пытался? Я соплями почему отдаю - потому что это единственный вариант хоть как - то узнать дошла порция до клиента или нет. Если запросил следующую, то дошла, если по новой со старого смещения, то нет. А ты мне что предлагаешь? Видел я эти скрипты с докачкой, толку? Запросил клиент range 1234-122999999/123000000, отдал наш скрипт ему этот диапазон и записал себе- отдано. А принято?
Тот код что я выложил - работает, и wget и reget в конце концов закачают файло, никуда не денутся, просто реализация кривая по сути, хотелось чего ни будь светлого и чистого...
 

desperado

Новичок
суть проблемы:
Как возомжно вести учёт объёма скачанной информации авторизованным пользователем?
---
на нее был да ответ (в том числе и мной)
---

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

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

псы. работающий код, но работающий криво - это не работающий код.
 

che

Guest
Originally posted by desperado
суть проблемы:
Как возомжно вести учёт объёма скачанной информации авторизованным пользователем?
---
на нее был да ответ (в том числе и мной)
---

сейчас жы ты хочешь посчитать не сколько ты отдал клиенты, а сколько он получил, что реально разные вещи...
Блин, не прошло и пол года, а ты уже понял. Дааа!!! Сколько ты отдал и сколько он получил - это разные вещи. А вопрос - учёт объёма скачанной информации. А теперь убеди меня в том что скачанная инфа - это то что ты отдал.
А насчет нахлест, не нахлест - какая пофигу разница? Там же по коду понятно - клиент запрашивает диапазон, я ему отдаю от того смещения что он попросил , просто не всё. Пусть просит как хочет, хоть вдоль, хоть поперек.
 

desperado

Новичок
за какой трафик ты платишь:
1) за тот, что у тебя ушел из сервера?
2) за тот, что получил пользователь?

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

хинт:
вообщем для приближение к истинным размер, которые получил ползователь используй connection_status()... перед тем, как записать размер отданного блока к общей сумме - проверяй оное... если пользователь (или кто-то еще) порвал коннект, то не записывай или как ты там это хочешь. погрешность оценки - будет равна объему, выдаваемому в цикле за раз (а не заказанному объему).
 

che

Guest
Где!!! Где!!! Где было сказано про деньги. Какая оплата? Мне пофигу за что платишь ты, так же как тебе пофигу за что плачу я. Кто тебе сказал, что я считаю трафик за который я буду платить? Кто? Кто бы это ни был - тебя обманули. И фишка как раз таки в том чтобы не отдавать лишних байт, не убедившись что предыдущие получены. Что и было исполнено. Но так как http к таким извратам не приспособлен, добро пожаловать в tcp. Там такое есть. Можно попробовать. Если делать нечего и нервы крепкие.
 

neko

tеam neko
Но так как http к таким извратам не приспособлен, добро пожаловать в tcp
добро пожаловать в osi
это вообще невозможно кроме как на уровне application layer
в данном случае приложением является браузер + http или "качалка" и они таких функций не имеют
 

desperado

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

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

раньше я отдавал данные вот так:
PHP:
  while(!feof($file_hand) && (connection_status()==0)){ 
    print fread($file_hand,$chunk_size);
    if(connection_status()==0){
      $sent_out += $chunk_size;
    }
    flush(); 
    sleep(1);
  }
где - $chunk_size был равен, как правило, 32kb (т.е. со скоростью, с которой отдавалось пользователю), а $sent_out - отданный объем с погрешностью не более 32kb.

если сделать ограничение в один проход, то не сложно считать скаченное пользователем (условно), по запрошенным "HTTP_RANGE", но опять же - погрешность будет в размере отданного.

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

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

che

Guest
Originally posted by neko
добро пожаловать в osi
это вообще невозможно кроме как на уровне application layer
в данном случае приложением является браузер + http или "качалка" и они таких функций не имеют
?
tcp, здается мне, ниже уровнем, ибо транспортный, и кто как не он обеспечивает контроль за надежной(читай подтвержденной) доставкой.
я уже подсказал - проверяй connection_status() перед отправкой нового блока данных (при этом разрывать ничего не надо), тебе и докачка будет... и проходов будет сколько угодно... и более точная проверка - получил пользователь данные или нет.
Ну что ты такой упрямый. То что коннекшн в порядке каким образом говорит тебе о том что юзер данные получил? Ну проверил ты его. В порядке. Отослал новую пачку. Опять проверил. Опять в порядке. Опять отослал. а юзер только только первую докачивает. И тут обрыв, смотрим коннекшн и говорим Ага!. А две пачки ушли в пустоту. Или я где что упустил?
 
Сверху