
У меня есть этот веб-сайт, где если пользователь отправляет форму, скрипт python выполняется через страницу php, а скрипт python создает zip-файл и должен предложить его пользователю для загрузки по ссылке. Файл может быть огромным (несколько ГБ).
Поскольку я работаю на университетском сервере, я строго привязан к их серверным правилам и возможностям. Вот в чем проблема:
Веб-сайт хранится в /data/mywebsite
, который имеет ограниченное дисковое пространство. Конечно, он принадлежит , www-data
поскольку в основном он доступен через мой сервер Apache.
Мне предлагают 1 ТБ хранилища в /experimentdata/
, которое ДОСТУПНО ТОЛЬКО одному конкретному пользователю, скажем theuser
. Это потому, что эта папка является монтированием samba, к которому может получить доступ один и конкретный идентификатор пользователя.
Чтобы создать файл в /experimentdata
, я использую sudo -u theuser
команду, которая создаст файл /experimentdata/downloadme.zip
как пользователь theuser
. Теперь моя проблема: как я могу предложить этот файл по ссылке для загрузки через Apache?
Я думал об использовании символической ссылки, которую я вставляю, например, /data/mywebsite/download/downloadme.zip
. Проблема в том, что у пользователя www-data
нет абсолютно никаких прав на чтение файла!
Как я могу разрешить пользователю загружать файл /experimentdata/downloadme.zip
с помощью пользователя www-data
через пользователя theuser
?
Я хотел бы прямо сказать, что вовлечение sudo -u theuser
абсолютно нормально. Но я не знаю, как сделать ссылку из этого куда-то за пределами папки моего веб-сайта.
PS: Если вам нужна дополнительная информация, пожалуйста, спрашивайте.
решение1
Я думаю, что нужно сделать так, чтобы ваш php
/ python
возвращал данные напрямую вместо apache
. Ваш код может делать то же самое, что apache
и . По моему опыту, это намного лучше, чем открывать другой каталог и/или использовать sudo
, или менять права доступа к файлам для apache
и т. д.
Если программа создает большой файл быстрее, чем интернет-соединение, то вы можете передавать данные напрямую из своей программы, что устраняет необходимость в дополнительном файле данных, коде для управления им и механизмах его запоминания.
Этот ответ на Stack Overflow показывает, как работает код в php
.https://stackoverflow.com/a/4357904/5484716.
Для программ, которые будут вызываться таким образом, исключите весь stderr
потоковый вывод и убедитесь, что код возврата из вашего процесса Python точно отражает успешность или неудачу процесса.
В примерах ниже показаны popen()
вызовы, которые вы могли бы использовать в приведенном выше примере сценария из stackoverflow. Я добавил exec 2>/dev/null;
к команде shell. Это гарантирует, что никакой вывод не попадет в stdandard error, даже из самой оболочки, поскольку наличие данных, поступающих как на , так и на , stderr
может stdout
стать источником взаимоблокировок с popen()
.
Если вы хотите загрузить файл диска своему пользователю:
$fp = popen('exec 2>/dev/null; sudo -u theuser cat yourfile.zip', 'r');
Если вы хотите загрузить данные из активного процесса:
$fp = popen('exec 2>/dev/null; sudo yourpythonscript arg argN', 'r');
Эти командные строкиявляютсяКоманды оболочки и метасимволы оболочки должны быть заключены в кавычки соответствующим образом.
Во втором методе сервер начнет отправлять данные немедленно. Когда пользователь успешно отправит форму, он немедленно увидит диалоговое окно «сохранить как» в своем браузере. Как только пользователь выберет выходной файл, ваш php
скрипт передаст данные напрямую по проводам в удаленный файл.
Скрипт python
должен вывеститолькоданные zip на стандартном выводе и возвращают код выхода, который точно отражает успех или неудачу процесса zip. В python
скрипте следует записать вывод на sys.stdout
, например zf = ZipFile(sys.stdout, ...
.
Крайне важно вызвать pclose()
и проверить возвращаемое значение., потому что это будет единственный способ узнать, был ли zip успешным или нет. Если pclose()
возвращается что-то, кроме 0, что-то не так.
То, как файл обрабатывается клиентом, зависит от настроек этих response headers
и других параметров: content-type:
, content-encoding:
, и content-disposition:
См.:http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html, посмотрите на response-header
и entity-header
информацию.