Выдача файла php скриптом

1. CROWS (02.03.2011 / 17:07)

session_start();


if (!isset($_SESSION['load']) || $_SESSION['load']=="" || $_SERVER['HTTP_REFERER']!=="http://site.org/file".$_GET['id']."")
    {
Header ('Location: http://site.org/file'.$_GET['id']);
exit();

    }else{
$file = ("путь к файлу");
header ("Content-Type: application/octet-stream");
header ("Accept-Ranges: bytes");
header ("Content-Length: ".filesize($file)); 
header ("Content-Disposition: attachment; filename=".$file);  
readfile($file);
         }


2. KOZZ (02.03.2011 / 17:07)
http://www.manhunter.ru/webmaster/179_zaschita_faylov_na_servere_ot_pryamih_ssilok_antileech.html

3. CROWS (02.03.2011 / 17:11)
Суть вот в чем:

на сайте есть страницы с описанием файлов (http://site.org/file'.$_GET['id']). На этой странице расположена ссылка на скачивание файла, код скачивания файла выше. Это сделано с той целью, чтобы скрыть прямые ссылки и чтобы скачивать файл можно было только прийдя с http://site.org/file'.$_GET['id']

В связи с тем, что мы изменяем прямой адрес к файлу на адрес http://site.org/load'.$_GET['id'], выдача файла происходит с помощью php скрипта (код в else).

Но вот огромная проблема есть: при скачивании файла все 256 МБ оперативы забиваются за раз.

Как решить проблему?

4. KOZZ (02.03.2011 / 17:14)
может что то типа flush() ??
я тебе ссылку дал, там подобный скрипт только все разжевано и удобно.

5. CROWS (02.03.2011 / 17:16)
Ботаник eGo (2 Марта 2011 / 17:14)
может что то типа flush() ??
я тебе ссылку дал, там подобный скрипт только все разжевано и удобно.
Сейчас посмотрю, только врядли там найдется решение этой проблемы.

6. Lugaro (02.03.2011 / 17:19)
2. Ботаник eGo, Там косяк в нем, при выдаче юзер не получит сразу файл, а будет ждать пака скрипт полностью не выдаст файл, в циклах flush() нужно добавить.

7. KOZZ (02.03.2011 / 17:20)
6. .::lugaro::., там по - моему это указано где - то..
P.S: я об этом в 4 посте говорил smile

8. Дмитрий (02.03.2011 / 17:20)
1) Накатай файл-ресайз (типа как ресайз фотографий в моторе) и выдавай файлы через него.
2) Чтобы при каждом скачивании ссылка была разная, прикрепляй к джет-запросу сгенерированный код, а сам код пиши в сессию.
3) При скачивании проверяй, если код из ссылки совпадает с кодом в сессии, выдавай TRUE и отдавай файл, в протифном случае - FALSE.
4) При удачном совпадении и удачной загрузке снова генерируй код и перезаписывай сессию.
5) Путь к файлу ресайза для пущей красоты скрой с помощью мод-реврайта.
К примеру, вместо http://site.ru/resize.pgp?fail=12345&specialkod=12345679&
измени на http://site.ru/12345/12345679

Вот и вся любовь. По сути, работы на 15 минут.

9. Lugaro (02.03.2011 / 17:23)
7. Ботаник eGo, точно, это я же и писал D

10. Дмитрий (02.03.2011 / 17:23)
о том как отдать различные расширения файлов с помощья ресайза, читай тут: http://www.ipm.kstu.ru/it/lec/7.php

11. CROWS (02.03.2011 / 17:29)
8. dima.london, нет, файлы должны быть в том же виде, что они и есть. По второму и третему пункту: дак полный путь надо будет выдавать.

Добавлено через 02:19 сек.
И можно обойтись без дополнительных параметров в GET, а просто сессией, т.е. так, как я написал в первом посте.

Добавлено через 04:54 сек.
4. Ботаник eGo,

while (!feof($f)) { 
flush();
  if (connection_aborted()) { 
    fclose($f); 
    break; 
  } 
  echo fread($f,10000); 

  sleep(1); 
}

Так или его после нужно ставить?

12. Дмитрий (02.03.2011 / 17:36)
11. -V_o_R_o_N_a-, при чем здесь полный путь? К примеру, в файле ресайда пропиши папку и подпапку, где прячешь файл, а в джет-запросе передавай только имя файла и сгенерированный код.
Сейчас поищу код как я себе сделал выдачу мп3-файлов с помощью ресайза.

13. CROWS (02.03.2011 / 17:39)
12. dima.london, ок, жду.

14. Дмитрий (02.03.2011 / 17:45)
Вот так выглядит у меня файл выдачи мп3-файла (mp3.php):
if(isset($_GET['file'])) {$file = $_GET['file'];} else {$file = '';}

if (preg_match('|^[a-z0-9_\.\-\/]+$|i', $file)){
    $ext = strtolower(substr($file, strrpos($file, '.') + 1));
    
    if($ext == 'mp3'){
        $filename = 'папка/подпапка/' . $file;
        $filename = file_get_contents($filename);
        header('Content-Disposition: inline; filename="' . $file . '"');
        header('Content-type: audio/mpeg');
        header('Content-Length: ' . strlen($filename));
        echo $filename;
    }
}
exit;
Ссылка на скачивание имеет 2 переменные (ид файла в базе и сгенерированный код из сессии).
Путь к загрузке лежит через простенький скрипт, где у меня идет проверка сгенерированного кода на совпадение с сессией, существование файла и запись количества скачиваний (+1).
То есть если все гут, я пишу +1 скачивание и отдаю файл:
header ('Location: mp3.php?file=имя_файла.mp3); exit;


15. CROWS (02.03.2011 / 17:49)
14. dima.london, благодарю за код.

А file_get_contents и echo тоже ведь будут оперативу хавать) Файн, например в 100 МБ, а оперативы на ВДС 256)

16. Дмитрий (02.03.2011 / 17:49)
Преимущества:
1) Прямой путь к файлу скрыт. Скачать по прямой ссылке невозможно.
2) В ссылке есть сгенерированный код из сессии, что создает большие трудности для скачивания файла роботом или для граба твоего контента.

Ну, для себя, для пущей безопасности и накрутки количества скачиваний роботами, для гостей я добавил еще и каптчу.

Добавлено через 01:21 сек.
хз, не должно. Хотя, вроде как хавает.

17. CROWS (02.03.2011 / 17:55)
выдача ведь тоже скриптом происходит.

18. Lugaro (02.03.2011 / 19:42)
11. Перед sleep напиши
14. dima.london, Загнется твой скрипт при больших файлах, да и нет возможности докачки что не мало важно
15. file_get_contents будет

19. Саня (02.03.2011 / 20:48)
$ext = strtolower(substr($file, strrpos($file, '.') + 1)); // костыль детектед
//Good
$ext = pathinfo($file,PATHINFO_EXTENSION);

20. Сааааа-нёёёёё-к (02.03.2011 / 20:53)
так проще запоминаеться))
$ext = pathinfo($file);
echo $ext['extension'];

21. Дмитрий (03.03.2011 / 14:23)
.::lugaro::., Ботаник eGo, вариант из 4 поста работает в 2-3 раза дольше, даже при использовании flush(). К тому же не поддерживает потоковое воспроизведение файла.
Возможно, я что-то не так делаю. Из того кода я только изменил директории на свои, добавил flush() (что само собой существенно ускорило отдачу файла) и изменит MIME тип файла на audio/mpeg (так как использую для обработки мп3-файла.

Все равно, скорость на порядок ниже той, если просто выдавать файл как я описал в моем варианте).

22. KOZZ (03.03.2011 / 14:40)
dima.london, я даже не представляю как допустим твой file_get_contents() выдаст файл в 500++ мб.
да и не думаю что file_get_contents() быстрее fread например.
без докачки очень худо будет тоже
P.S:
<?
if(isset($_GET['file'])) {$file = $_GET['file'];} else {$file = '';}
# а ведь так элегантней:
$file = (isset($_GET['file'])) ? $_GET['file'] : '';
?>


23. Дмитрий (03.03.2011 / 14:52)
22. Ботаник eGo, само сабой так элегантнее.
Я просто надеюсь на твою помощь. Все-таки и я решил добавить докачку, но явно что-то делаю не так.....

24. Lugaro (03.03.2011 / 15:30)
21. dima.london, Ну дык там же sleep стоит и отдается кусками по 10кб в сек, поменяй скорость и выдавай кусками по больше + если тестил на денвере flush там до балалайки

URL: https://visavi.net/topics/19287