
Eu tenho este site, onde se o usuário enviar um formulário, um script python é executado através de uma página php, e o script python cria um arquivo zip e deve oferecê-lo ao usuário para download através de um link. O arquivo pode ser enorme (alguns GB).
Como estou trabalhando em um servidor universitário, estou estritamente vinculado às regras e capacidades do servidor. Aqui está o problema:
O site está armazenado em /data/mywebsite
, que possui espaço em disco limitado. É claro que isso é propriedade de, www-data
pois é acessível principalmente pelo meu servidor Apache.
Me oferecem 1 TB de armazenamento /experimentdata/
, que só é ACESSÍVEL por um único usuário específico, por exemplo theuser
. Isso ocorre porque esta pasta é uma montagem samba que pode ser acessada por um ID de usuário único e específico.
Para criar o arquivo em /experimentdata
, eu uso um sudo -u theuser
comando que irá criar o arquivo /experimentdata/downloadme.zip
como usuário theuser
. Agora meu problema é: Como posso oferecer esse arquivo através de um link para download através do Apache?
Pensei em usar um link simbólico que coloquei, por exemplo, /data/mywebsite/download/downloadme.zip
. O problema é que o usuário www-data
não tem absolutamente nenhuma permissão para ler o arquivo!
Como posso permitir que o usuário baixe o arquivo /experimentdata/downloadme.zip
com o usuário www-data
através do usuário theuser
?
Gostaria de dizer explicitamente que envolver sudo -u theuser
é absolutamente aceitável. Mas não sei como criar um link para algum lugar fora da pasta do meu site.
PS: Se precisar de alguma informação adicional, por favor pergunte.
Responder1
Acho que o que você deve fazer é fazer com que você php
/ python
retorne os dados diretamente em vez de apache
. Seu código pode fazer a mesma coisa apache
. Na minha experiência, isso é muito melhor do que abrir outro diretório e/ou usar sudo
ou alterar as permissões de arquivo para apache
etc.
Se o programa produzir o arquivo grande mais rápido do que a conexão com a Internet, você poderá transmitir os dados diretamente do seu programa, o que elimina o arquivo de dados extra e o código para gerenciá-lo e os mecanismos para lembrá-lo.
Esta resposta no Stack Overflow mostra como o código funciona em php
.https://stackoverflow.com/a/4357904/5484716.
Para programas que serão chamados dessa forma, elimine toda stderr
a saída do fluxo e certifique-se de que o código de retorno do seu processo python reflita com precisão o sucesso ou a falha do processo.
Os exemplos abaixo mostram as popen()
chamadas que você usaria no cenário de exemplo acima do stackoverflow. Anexei exec 2>/dev/null;
o comando shell. Isso garante que nenhuma saída vá para o erro padrão, mesmo do próprio shell, porque ter dados chegando em ambos stderr
pode stdout
ser uma fonte de conflitos com popen()
.
Se você deseja baixar o arquivo do disco para o seu usuário:
$fp = popen('exec 2>/dev/null; sudo -u theuser cat yourfile.zip', 'r');
Se você deseja baixar os dados do processo ativo:
$fp = popen('exec 2>/dev/null; sudo yourpythonscript arg argN', 'r');
Essas linhas de comandosãocomandos shell e precisam ser citados apropriadamente para metacaracteres shell.
No segundo método, o servidor começaria a enviar os dados imediatamente. Quando o usuário envia o formulário com êxito, ele vê imediatamente uma caixa de diálogo "salvar como" em seu navegador. Assim que o usuário seleciona o arquivo de saída, seu php
script transmite os dados diretamente pela rede e para o arquivo remoto.
O python
script deve imprimirapenasos dados zip na saída padrão e retorna um código de saída que representa com precisão o sucesso ou a falha do processo zip. No python
script deve-se escrever a saída em sys.stdout
, por exemplo zf = ZipFile(sys.stdout, ...
.
É fundamental ligar pclose()
e verificar o valor de retorno, porque essa será a única maneira de saber se o zip foi bem-sucedido ou não. Se pclose()
retornar algo diferente de 0, algo está errado.
A forma como o arquivo é tratado pelo cliente depende das configurações destes response headers
e de outros: content-type:
, content-encoding:
, e content-disposition:
Veja:http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html, veja o response-header
e as entity-header
informações.