Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > php и htaccess: скачивание файлов


Автор: Frozen_Coyote 14.11.2012, 14:13
Привет, 

проблема следующая: есть директория с файлами, в которой лежит htaccess. В нем прописано: 

Код

Order Deny,Allow
Deny from all


выше уровнем лежит файл download.php который принимает в себя параметр file=какое_то_имя_файла.rar. На него переводит корневой .htaccess, в котором указано, что скачиваемые файлы с определенными расширениями перебрасывать в скрипт download.php. Код download.php
Код

$filename = $_SERVER["DOCUMENT_ROOT"]."/files/file/". $file;
header("Cache-Control: public");
header("Content-Description: File Transfer");
header('Content-disposition: attachment; filename='.basename($filename));
header('Content-Type: application/octetstream');
header("Content-Transfer-Encoding: binary");
header('Content-Length: '. filesize($filename));
readfile($filename);


Это все работает, все хорошо. НО!

Если htaccess лежит в вышеописаной директории - браузер выдает "форбидден", если убираю его - файл скачивается нормально, при этом перестрел на download.php рабоатет отлично - это видно в адресной строке, т.е. файл забирается через readfile. Почему же когда htaccess лежит в файловой директории, выдается запрет? Ведь, насколько я понимаю, локальные скрипты все равно имеют доступ к папке? Как быть, Что делать?


Автор: Aliance 14.11.2012, 14:28
Файлы download.php и какое_то_имя_файла.rar - в одном каталоге?

Автор: Frozen_Coyote 14.11.2012, 14:46
нет

струтктура такая:

files
|____file
        |_____.htaccess
        |_____какое_то_имя_файла.rar
downalod.php

Автор: Aliance 14.11.2012, 15:47
Цитата(Frozen_Coyote @  14.11.2012,  15:13 Найти цитируемый пост)
выше уровнем лежит файл download.php который принимает в себя параметр file=какое_то_имя_файла.rar. На него переводит корневой .htaccess, в котором указано, что скачиваемые файлы с определенными расширениями перебрасывать в скрипт download.php.

то есть человек обращается к файлу напрямую? или все же в  download.php? урл напиши

Автор: Frozen_Coyote 14.11.2012, 16:24
Смотри:

если человек кликает на ссылку с href=http://www.domen.com/files/file/какое_то_имя_файла.rar - ему запрет, это справедливо
если человек кликает на ссылку с href=http://www.domen.com/download.php?file=какое_то_имя_файла.rar - ему тоже запрет, что неясно. 

Если убрать из директории http://www.domen.com/files/file/ файл .htaccess с запретом, то при клике на ссылку "вариант 1" происходит преобразование в "вариант 2" и скачивание доступно, это логично и правильно. А если его там оставить - то, при клике на "вариант  1" получается интересная вещЬ: ощущение такое, что "осмотр" запрещающего файла htaccess в директории с файлами в директории http://www.domen.com/files/file/ осуществляется РАНЬШЕ, нежели преобразование к download.php, дескать "клик на ссылку - апач смотрит директорию с файлами , видит в ней запрещающий  htaccess и сразу форбидден". До преобразования дело не доходит.

files
|____file
        |_____.htaccess // в этом файле стоит запрет на прямое скачивание (Deny From All)
        |_____какое_то_имя_файла.rar
download.php
.htaccess //в этом файле идет преобразоваение ссылки (RewriteEngine on; RewriteRule ^(.*).(rar|zip|pdf|arj|gzip|tgz)$ /download.php?file=$1.$2 [R,L])


Автор: Aliance 14.11.2012, 16:36
Я бы просто файлы вынес за document root, тогда запрет не нужен вовсе.

Автор: Frozen_Coyote 14.11.2012, 17:05
это да, но хотелось бы вот этот механизм осознать и сконструировать

Автор: skyboy 14.11.2012, 21:01
не по вопросу, но по проблеме. readfile убьет сервак на большом файле, так как считывает все данные в память.
тебе надо посмотреть X-SendFile или другие подобные механизмы: скрипт будет только проверять права и говорить НТТР-серверу: "нормалек, отдай ему этот файл"
Цитата(Frozen_Coyote @  14.11.2012,  13:13 Найти цитируемый пост)
 в которой лежит htaccess. В нем прописано: 

я вот только не пойму, на кой вообще Deny, если 
Цитата(Frozen_Coyote @  14.11.2012,  13:13 Найти цитируемый пост)
переводит корневой .htaccess, в котором указано, что скачиваемые файлы с определенными расширениями перебрасывать в скрипт download.php

если ты про RewriteRule, то, получается, через НТТР-запрос ну, никак не обратиться к файлам — всегда будет редирект на download.php

Автор: Frozen_Coyote 14.11.2012, 21:09
Да я и не говорю что Deny это идеальное решение, это я пытаюсь сделать механизм "отдачи файла только своему, без поптыки скачивания по прямой ссылке". За X-Send спасибо - буду изучать. Это надстройка какая то, она штатная у хостеров или надо его умолять ее подключить?

насчет же "всегда переводиться на download.php" вот тут то и удивление - я так понимаю при deny в htacces в директории дело до download не доходит - сразу форбидден - download не отрабатвает

Автор: skyboy 14.11.2012, 21:49
Цитата(Frozen_Coyote @  14.11.2012,  20:09 Найти цитируемый пост)
я так понимаю при deny в htacces в директории дело до download не доходит

у меня вопрос был: даже при твоем подходе с readfile, зачем вообще deny?

Автор: Frozen_Coyote 14.11.2012, 21:56
ну у меня тема такая - я хочу на уровне некоего программного комплекса выстраивать такой расклад: если допустим в админке включена опция "скачивание только для зарегистрированных пользователей" - отдается все через скрипт, если "для всех" то по прямым ссылкам. Беда в том, что если включена опция "зарегистрированнм пользователям" но человек вводит в адресную строку адрес типа www.domen.ru/download.php?file=такойтофайл.rar то он качается безо всякой регистрации )) вот и начал поиски )) не подскажешь как грамотнее реализовать?

Автор: skyboy 14.11.2012, 22:04
Цитата(Frozen_Coyote @  14.11.2012,  20:56 Найти цитируемый пост)
но человек вводит в адресную строку адрес типа www.domen.ru/download.php?file=такойтофайл.rar то он качается безо всякой регистрации ))

а проверка-то есть на зарегистрированность в download.php? Deny к этому, кста, вообще отношения не имеет

Автор: Frozen_Coyote 14.11.2012, 22:16
теперь то я понимаю, что не имеет..

да, в него передается uin пользователя

Автор: skyboy 14.11.2012, 22:24
Цитата(Frozen_Coyote @  14.11.2012,  21:16 Найти цитируемый пост)
да, в него передается uin пользователя 

как передается?
и почему, в таком случае, 
Цитата(Frozen_Coyote @  14.11.2012,  20:56 Найти цитируемый пост)
он качается безо всякой регистрации

?

Автор: Frozen_Coyote 14.11.2012, 22:50
как я реализовал. Перед выдачей пользователю страницы (при режиме "скачка для авторизованных юезерей") php конвертирует все линки в вид, при котором href="javascript:void(0)" а ONCLICK - отрабатывает javascript функцию
Код


        $("body").append("<div id=\"DownloadFileWindow\"></div>");
        $("div#DownloadFileWindow").css("display", "none");
        $("div#DownloadFileWindow").css("background-color", "#ffffff");
        $("div#DownloadFileWindow").css("border", "#999999 1px solid");
        $("div#DownloadFileWindow").css("width", "320px");
        $("div#DownloadFileWindow").css("height", "240px");
        $("div#DownloadFileWindow").css("position", "fixed");
     $("div#DownloadFileWindow").css("top", (($(window).height() - $("div#DownloadFileWindow").height()) / 2 - 10) + "px");
        $("div#DownloadFileWindow").css("left", (($(window).width() - $("div#DownloadFileWindow").width()) / 2 - 10) + "px");
        $("div#DownloadFileWindow").css("z-index", "11");
        $("div#DownloadFileWindow").append("<div style=\"position: absolute; right: 0; top: -30px;\"><a href=\"javascript:void(0);\" onClick=\"$('#DownloadFileWindow').remove(); CreateOverlay(0);\"><img src=\"/img/close.png\" alt=\"\" border=\"0\" /></a></div>");

        $("div#DownloadFileWindow").append("<iframe src=\""/download.php?allow=" + allow +  "&own_user_session=" + own_user_session + "&file=" + file + "\" frameborder=\"0\" class=\"download_frame\" ></iframe>");


        $("div#DownloadFileWindow").css("display", "block");


результат: на черном оверлее, перекрывающим старницу открывается сэмулированное типа окошко, в которое подгружается iframe, сурсом которого является этот download.php. параметрами которого являются как раз сессия юзера, имя файла и тд. Ну высвечивается капча там, юзер вводит код ок и пошла скачка. Это нюансы. они работают и все ок. Но в этом же download.php должна быть возможность ПРОСТО отдачи файла, если выставлен режим "скачка для всех кому угодно" (allow = 2). Я не знаю, может я конечно невменяемо объясняю и наворотил лишнего - но логика у мя так сработала. 

Автор: skyboy 14.11.2012, 23:06
у тебя регистрация и авторизация, надеюсь, привязана к http://php.net/session?
коль так, то не надо ничего менять джаваскриптом. тем более, это только видимость защиты от прямого скачивания.
проверяй сессию на предмет данных о регистрации

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)