
Tengo este sitio web, donde si el usuario envía un formulario, se ejecuta una secuencia de comandos de Python a través de una página PHP, y la secuencia de comandos de Python crea un archivo zip y debe ofrecérselo al usuario para que lo descargue a través de un enlace. El archivo podría ser enorme (unos pocos GB).
Como trabajo en un servidor universitario, estoy estrictamente sujeto a las reglas y capacidades de su servidor. Aquí está el problema:
El sitio web se almacena en /data/mywebsite
, que tiene un espacio en disco limitado. Por supuesto, esto es propiedad de, www-data
ya que mi servidor Apache puede acceder a él principalmente.
Me ofrecen 1 TB de almacenamiento en /experimentdata/
, al que SÓLO puede ACCEDER un usuario único y específico, digamos theuser
. Esto se debe a que esta carpeta es un montaje de samba al que se puede acceder mediante una identificación de usuario única y específica.
Para crear el archivo en /experimentdata
, uso un sudo -u theuser
comando que creará el archivo /experimentdata/downloadme.zip
como usuario theuser
. Ahora mi problema es: ¿Cómo puedo ofrecer este archivo a través de un enlace para su descarga a través de Apache?
Pensé en usar un enlace simbólico que puse, por ejemplo /data/mywebsite/download/downloadme.zip
,. ¡El problema con esto es que el usuario www-data
no tiene ningún permiso para leer el archivo!
¿Cómo puedo permitir que el usuario descargue el archivo /experimentdata/downloadme.zip
con el usuario www-data
a través del usuario theuser
?
Me gustaría decir explícitamente que involucrarse sudo -u theuser
está absolutamente bien. Pero no sé cómo crear un enlace a partir de eso a algún lugar fuera de la carpeta de mi sitio web.
PD: Si necesita alguna información adicional, por favor pregunte.
Respuesta1
Creo que lo que hay que hacer es que php
/ python
devuelva los datos directamente en lugar de apache
. Su código puede hacer lo mismo que apache
hace. En mi experiencia, esto es mucho mejor que abrir otro directorio y/o usar sudo
, o cambiar los permisos de archivos apache
, etc.
Si el programa produce el archivo grande más rápido que la conexión a Internet, entonces puede transmitir los datos directamente desde su programa, lo que elimina el archivo de datos adicional y el código para administrarlo y los mecanismos para recordarlo.
Esta respuesta en Stack Overflow muestra cómo funciona el código php
.https://stackoverflow.com/a/4357904/5484716.
Para los programas que se llamarán de esta manera, elimine toda stderr
la salida de flujo y asegúrese de que el código de retorno de su proceso de Python refleje con precisión el éxito o el fracaso del proceso.
Los siguientes ejemplos muestran las popen()
llamadas que usaría en el escenario de ejemplo anterior desde stackoverflow. Lo he antepuesto exec 2>/dev/null;
al comando de shell. Esto garantiza que ninguna salida genere un error estándar, incluso desde el propio shell, porque tener datos provenientes de ambos stderr
puede stdout
ser una fuente de interbloqueos con popen()
.
Si desea descargar el archivo de disco a su usuario:
$fp = popen('exec 2>/dev/null; sudo -u theuser cat yourfile.zip', 'r');
Si desea descargar los datos del proceso activo:
$fp = popen('exec 2>/dev/null; sudo yourpythonscript arg argN', 'r');
Estas líneas de comandosoncomandos de shell y deben citarse adecuadamente para los metacaracteres de shell.
En el segundo método, el servidor comenzaría a enviar los datos inmediatamente. Cuando el usuario envía correctamente el formulario, ve inmediatamente un cuadro de diálogo "guardar como" en su navegador. Tan pronto como el usuario selecciona el archivo de salida, su php
secuencia de comandos transmite los datos directamente a través del cable y al archivo remoto.
El python
guión debería imprimirse.sololos datos zip en la salida estándar y devuelve un código de salida que representa con precisión el éxito o el fracaso del proceso zip. En python
el script se debe escribir la salida sys.stdout
, por ejemplo zf = ZipFile(sys.stdout, ...
.
Es fundamental llamar pclose()
y verificar el valor de retorno., porque esa será la única forma de saber si el zip tuvo éxito o no. Si pclose()
devuelve algo distinto de 0, algo anda mal.
La forma en que el cliente maneja el archivo depende de la configuración de estos response headers
y otros: content-type:
, content-encoding:
y content-disposition:
Consulte:http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html, mira el response-header
y la entity-header
información.