Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Отдача файлов скриптом 
:(
    Опции темы
WolfAlone
Дата 28.8.2012, 00:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


В экстазе
***


Профиль
Группа: Завсегдатай
Сообщений: 1010
Регистрация: 16.9.2008
Где: Рай

Репутация: 1
Всего: 5



Доброго времени суток!

Предо мной стоит задача, отдавать файлы через PHP (защищая их от прямого скачивания). Нашел множество решений, большинство из которых, по мнению "специалистов" (о уровне их квалификации я судить не могу) - потребляет очень много оперативной памяти. То есть, файл перед "отдачей" загружается в память целиком. Соответственно, если у нас лежит 10 файлов по 1Гб и их необходимо будет отдать все одновременно... Память на сервере, как я понял, может внезапно кончиться.

Нашел вот такой способ, который, по идее вроде бы как кушает памяти поменьше:
Код

<?php
$rFile = @fopen('file.zip', 'r');
$rOutput = fopen('php://output', 'w');
if($rFile)
{
    header('Content-Disposition: attachment; filename='.'file.zip');
    stream_copy_to_stream($rFile, $rOutput);
    exit();
}
?>


Подскажите пожалуйста, насколько затратный по объёму ОЗУ такой способ, хотя бы примерно?

Возможно есть какие-то более оптимальные варианты, для экономии оперативной памяти? 


--------------------
И сказал Бог: "Тогда я построю свой мир с блэк-джеком и шлюхами!"

Ф топку Ubuntu, Debian наше фсё!

(с) Евгений Вольф
PM MAIL WWW ICQ Skype   Вверх
Sanchezzz
Дата 28.8.2012, 07:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1670
Регистрация: 19.11.2006
Где: Voronezh

Репутация: 41
Всего: 60



сделайте тестовый замер с помощью memory_get_usage и посмотрите сколько есть
Код

    $start  = memory_get_usage();
    echo $start  / 1024, 'kb<br>';

    $foo = new stdClass;
    echo ( memory_get_usage() - $start ) / 1024  , 'kb<br>' ;
    
    $foo2 = new stdClass;
    echo ( memory_get_usage() - $start ) / 1024  , 'kb<br>' ;

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





 


--------------------
Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS.
PM MAIL Skype GTalk   Вверх
WolfAlone
Дата 28.8.2012, 10:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


В экстазе
***


Профиль
Группа: Завсегдатай
Сообщений: 1010
Регистрация: 16.9.2008
Где: Рай

Репутация: 1
Всего: 5



Sanchezzz, шикарно, спасибо! Сегодня протестирую!


--------------------
И сказал Бог: "Тогда я построю свой мир с блэк-джеком и шлюхами!"

Ф топку Ubuntu, Debian наше фсё!

(с) Евгений Вольф
PM MAIL WWW ICQ Skype   Вверх
WolfAlone
Дата 28.8.2012, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


В экстазе
***


Профиль
Группа: Завсегдатай
Сообщений: 1010
Регистрация: 16.9.2008
Где: Рай

Репутация: 1
Всего: 5



Поправил код:
Код

<?php
$start  = memory_get_usage();
$f = fopen('file.txt', 'w+');
fwrite($f, ($start  / 1024).' / ');
$rFile = @fopen('1.avi', 'r'); //Файл занимает ~700Мб
$rOutput = fopen('php://output', 'w');
if($rFile)
{
    header('Content-Disposition: attachment; filename='.'file.zip');
    while(stream_copy_to_stream($rFile, $rOutput))
    {
        fwrite($f,  ((memory_get_usage() - $start) / 1024).':') ;
    }
    fwrite($f, (memory_get_usage() - $start) / 1024) ;
    fclose($f);
    exit();
}
?>


Результаты:
1. Запуск скрипта ~300Кб
2. Внутри while ~2Кб
3. После while ~2Кб

Что-то мне подсказывает, что я что-то не так делаю... или буфер ("буфер" = объём "отъеденой" памяти) на самом деле может быть размером 1.5-2Кб для файла в ~700Мб?


--------------------
И сказал Бог: "Тогда я построю свой мир с блэк-джеком и шлюхами!"

Ф топку Ubuntu, Debian наше фсё!

(с) Евгений Вольф
PM MAIL WWW ICQ Skype   Вверх
ksnk
Дата 28.8.2012, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



WolfAlone, Смешнее всего не то, что копирование файла функцией stream_copy_to_stream не занимает дополнительный объем. Смешно то, что после этой функции куда-то деваются лишние 2k памяти. Либо это баг в php, либо погрешностьизмерения  smile 

Впрочем, кто-то, судя по комментариям уже натыкался на такое поведение этой функции.

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


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
WolfAlone
Дата 28.8.2012, 23:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


В экстазе
***


Профиль
Группа: Завсегдатай
Сообщений: 1010
Регистрация: 16.9.2008
Где: Рай

Репутация: 1
Всего: 5



ksnk, правильно ли я понял, что при таком методе отдачи файлов ("через скрипт", например для подсчёта кол-ва скачиваний файла), обём "отъедаемой" памяти для одного файла, для грубого расчёта нагрузки, можно брать величину 512Кб (вообще, в результате работы того скрипта, если сильно округилть, получиться ~350Кб ОЗУ, но для "надежности", будем считать, что условно, такой скрипт кушает 0.5Мб оперативки в течение всего времени затраченного на отдачу файла)?

Добавлено через 4 минуты и 41 секунду
Ещё, подскажите пожалуйста, если взять во внимание, что по умолчанию на выполнение скрипта интерпретатор PHP отводит 30сек., по прошествии этого времени отдача файла прекратиться?

Это сообщение отредактировал(а) WolfAlone - 28.8.2012, 23:43


--------------------
И сказал Бог: "Тогда я построю свой мир с блэк-джеком и шлюхами!"

Ф топку Ubuntu, Debian наше фсё!

(с) Евгений Вольф
PM MAIL WWW ICQ Skype   Вверх
ksnk
Дата 29.8.2012, 07:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Посмотрите на функцию readfile. Это, случайно, не то, что нужно? 

Для чего ведутся такие расчеты? Для определения нужных параметров в php.ini или для определения нужных объемов памяти в виртуальной машине?




--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
WolfAlone
Дата 29.8.2012, 11:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


В экстазе
***


Профиль
Группа: Завсегдатай
Сообщений: 1010
Регистрация: 16.9.2008
Где: Рай

Репутация: 1
Всего: 5



ksnk, подобные расчёты ведутся для вычисления объёма оперативной памяти, необходимой на серверной (физической) машине. Хочу поставить отдельный сервер, в качестве централизованного файло-хранилища. Файлы размером от нескольких Кб до не более ~1Гб. Номинальная нагрузка на сервер (для расчёта) 1000 одновременно скачиваемых файлов 24х7.

Расчитать нужно, именно объём оперативной памяти, необходимый для этой задачи.

Интересен именно объём потребляемой оперативной памяти по двум причинам:
Основная причина: я думаю, что "раздача файлов" не потребляет большое кол-во процессорных ресурсов
Косвеная причина: если придётся делать уменьшенную копию аналогичного сервера (сервиса), например на VPS (для экономии денег), все провайдеры из тех, что мне встречались (XEN, VmWare), предоставляют в пользование 1-2 ядра от Xeon ~2.4ГГц. Основное отличие тарифов друг от друга заключается только в объёме оперативной памяти.


Цитата(ksnk @  29.8.2012,  07:55 Найти цитируемый пост)
Посмотрите на функцию readfile. Это, случайно, не то, что нужно? 

Внимательно изучил Вашу ссылку, посмотрел пример: Example #1 Forcing a download using readfile(). В принципе, это как раз то, что мне нужно. Вопрос сключительно в том, какой из методов отдачи файла будет кушать наименьшее кол-во ОЗУ, растёт ли потребление ОЗУ пропорционально размеру файла (в каждом конкретном случае) и какой примерно объём ОЗУ выделяется (затрачивается) на скрипт отдающий файл.

Это сообщение отредактировал(а) WolfAlone - 29.8.2012, 11:40


--------------------
И сказал Бог: "Тогда я построю свой мир с блэк-джеком и шлюхами!"

Ф топку Ubuntu, Debian наше фсё!

(с) Евгений Вольф
PM MAIL WWW ICQ Skype   Вверх
Fortop
Дата 29.8.2012, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 20
Всего: 42



WolfAlone, а погуглите.
И даже по этому форуму.

Где-то были упоминания о том, как создавать временные ссылки через скрипт и отдавать скачивание на откуп тому же nginx
то ли Feldmarshal, то ли Ипатьев про это писали.


--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
WolfAlone
Дата 29.8.2012, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


В экстазе
***


Профиль
Группа: Завсегдатай
Сообщений: 1010
Регистрация: 16.9.2008
Где: Рай

Репутация: 1
Всего: 5



Цитата(Fortop @  29.8.2012,  12:33 Найти цитируемый пост)
Где-то были упоминания о том, как создавать временные ссылки через скрипт и отдавать скачивание на откуп тому же nginx

Безусловно есть альтернативные решения! Можно, например, написать на С/С++ маленькую программку, контроллируя выделяемую ей (ею) память буквально до килобайта, и с помощью программы отдавать файлы, но прежде всего, я хотел бы рассмотреть самое стандартное (простое) решение.

Это сообщение отредактировал(а) WolfAlone - 29.8.2012, 14:27


--------------------
И сказал Бог: "Тогда я построю свой мир с блэк-джеком и шлюхами!"

Ф топку Ubuntu, Debian наше фсё!

(с) Евгений Вольф
PM MAIL WWW ICQ Skype   Вверх
ksnk
Дата 29.8.2012, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Цитата(WolfAlone @  29.8.2012,  14:23 Найти цитируемый пост)
 прежде всего, я хотел бы рассмотреть самое стандартное (простое) решение.

Самое стандартное(с точки зрения php) решение - readfile. но для таких условий 
Цитата(WolfAlone @  29.8.2012,  11:37 Найти цитируемый пост)
Номинальная нагрузка на сервер (для расчёта) 1000 одновременно скачиваемых файлов 24х7.

оно не подойдет

Нормально по производительности такие задачи решаются только созданием временных "жестких" ссылок на скачивание файла. Сама скачка файла передоверяется в дальнейшем какому-нибудь nginx'у. 



--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
WolfAlone
Дата 29.8.2012, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


В экстазе
***


Профиль
Группа: Завсегдатай
Сообщений: 1010
Регистрация: 16.9.2008
Где: Рай

Репутация: 1
Всего: 5



Цитата(ksnk @  29.8.2012,  14:48 Найти цитируемый пост)
Нормально по производительности такие задачи решаются только

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

Какая примерно нагрузка (потребление ресурсов машины) будет при одновременном скачивании 10-и, 100-а файлов, размером допустим 10Мб? Где примерно пролегает граница, между тем когда "разумно" отдавать файлы скриптом и когда такой подход уже не оптимален, в виду каких-то причин? Как определить эту "границу"?


--------------------
И сказал Бог: "Тогда я построю свой мир с блэк-джеком и шлюхами!"

Ф топку Ubuntu, Debian наше фсё!

(с) Евгений Вольф
PM MAIL WWW ICQ Skype   Вверх
ksnk
Дата 29.8.2012, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



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

Цитата(WolfAlone @  29.8.2012,  16:18 Найти цитируемый пост)
Где примерно пролегает граница, между тем когда "разумно" отдавать файлы скриптом и когда такой подход уже не оптимален, в виду каких-то причин? Как определить эту "границу"? 

Зачем определять такую границу? Ну вообразите, что при 12 одновременных загрузках сервер еще шевелится, а 13 его роняет. Какой выход? Блокировать юзеров свыше 12-ти? Или пусть лучше файлы отдает сапожник nginx, который для этого ( эффективной работы со статическим контентом) специально и создавался? 


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
WolfAlone
Дата 29.8.2012, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


В экстазе
***


Профиль
Группа: Завсегдатай
Сообщений: 1010
Регистрация: 16.9.2008
Где: Рай

Репутация: 1
Всего: 5



Цитата(ksnk @  29.8.2012,  16:32 Найти цитируемый пост)
Зачем определять такую границу?

Такую границу, нужно определить для того, что бы знать, в каких случаях нужен nginx, а в каких нет. Например, в первой "версии" (основной) предполагается пиковая нагрузка в 1000 скачиваний - 24x7 - файл(ы, ов) по 100Мб каждый (это для расчёта). А если такой сервис уменьшить в масштабе, допустим в N раз? И у нас получиться пиковая нагрузка: 10 файлов, по 10Мб, 1000 скачиваний в сутки (в общей сложности). И, при таком раскладе ставить Nginx не имеет особого смысла (этого я не утверждаю, я лишь привожу пример/предположение). Вот, для этого я и хочу определить подобные границы.


--------------------
И сказал Бог: "Тогда я построю свой мир с блэк-джеком и шлюхами!"

Ф топку Ubuntu, Debian наше фсё!

(с) Евгений Вольф
PM MAIL WWW ICQ Skype   Вверх
Sanchezzz
Дата 29.8.2012, 16:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1670
Регистрация: 19.11.2006
Где: Voronezh

Репутация: 41
Всего: 60



X-Accel-Redirect
Далее пишем конфиг для никса где храним файлы и как будем обрабатывать все это
Код

location / {
   rewrite ^/download/(.*)/(.*)    /download.php?q=$2&key=$1 last;
}

location /files {
   root /home/host/www;
   internal;
}


далее создаем скрипт логики который будет это дело обслуживать и перенаправлять куда надо на файл
Код


$path = $_GET["q"];   // имя файла или какой другой индикатор который поможет нам узнать имя файла
$key = $_GET["key"]; //секретный ключ который мы получили ввели и проверили где то ниже верный не верный

$file = dirname(__FILE__).'/files/'.$path;
if (file_exists($file)) {
   header("Content-type: ".mime_content_type($file));
   header("Content-length: ".filesize($file));
   header("X-Accel-Redirect: /files/" . $path);
}


/download/ключ/имя_файла


Полноценная отдача файлов для не разумных пределов через чистый PHP долго не живет



Это сообщение отредактировал(а) Sanchezzz - 29.8.2012, 17:15


--------------------
Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS.
PM MAIL Skype GTalk   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0673 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.