Foros del Web » Programando para Internet » PHP »

Zona privada con descarga de .pdf

Estas en el tema de Zona privada con descarga de .pdf en el foro de PHP en Foros del Web. Hola foreros! Tengo que programar una zona privada de acceso restringido (los datos salen de una BD Mysql) y en esta zona y sólo en ...
  #1 (permalink)  
Antiguo 06/10/2005, 16:16
Avatar de damargon  
Fecha de Ingreso: junio-2003
Ubicación: Madrid
Mensajes: 386
Antigüedad: 14 años, 5 meses
Puntos: 3
Zona privada con descarga de .pdf

Hola foreros!

Tengo que programar una zona privada de acceso restringido (los datos salen de una BD Mysql) y en esta zona y sólo en esta saldrán listados unos archivos .pdf para que esos usuarios se los descarguen.

Tengo varias dudas de cuál sería el mejor método para implementarlo:
1 - .htaccess y .htpwd: no entiendo bien como puedo mantener desde php los datos de los usuarios desde un panel de administración programado en .php.

2 - Utilizar header(): he hecho pruebas con los scripts que hay en php.net y no me funciona bien ninguno. Me ha desesperado un poquito.

3- Subir los .pdf como binario a la base de datos y que de ahí se los descarguen los usuarios una vez estén logueados claro (este me permite no tener que usar el header para llamar a los archivos situados fuera del root del server).

Aquellos que os tengáis que haber peleado con este tema ¿qué me aconsejáis? ¿cuál es el sistema más sencillo de usar y de mantener?

¡¡Gracias por adelantado!!
  #2 (permalink)  
Antiguo 06/10/2005, 16:53
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 15 años, 11 meses
Puntos: 126
1) .. Es necesario que uses autentificación HTTP? .. Podrías usar sesiones simplemente y el script que gestione la descarga + autentificación/validación de tus usuarios.

2) Tendrías que concretar que navegador usas y código concreto.

3) No es cierto que el hecho de tener en binario tu archivo (sea un pdf o lo que sea) te va a envitar usar cabeceras HTTP (vía Header()) para llamar a tu archivo y forzar su descarga.

Un saludo,
  #3 (permalink)  
Antiguo 06/10/2005, 18:23
Avatar de mega82es  
Fecha de Ingreso: septiembre-2005
Mensajes: 38
Antigüedad: 12 años, 3 meses
Puntos: 0
* Lo recomendable es que los archivos los tengas fuera del root del server, para que no esten accesibles al teclear la url.

* En un archivo de configuracion o en MySQL almacena la ruta del directorio donde tienes guardados tus PDF's, para que sea mas facil cambiarlos de lugar si fuera necesario.

* En MySQL registra por cada pdf, el nombre del archivo y/o la ruta relativa al directorio root de documentos

* Utiliza sesiones y un fichero php que se encargue de las descargas (ej. descargar.php?id=15), valida si el usuario tiene derechos sobre el archivo con el id proporcionado y si los tiene, entonces utiliza el header para indicarle al navegador que lo que le vas a enviar es un documento PDF.

* Envia el fichero con readfile() o file_get_contents(). busca la documentacion de estas dos funciones, a ver cual te funciona mejor.

* Si necesitas hacer un listado, toma los datos de mySQL y hazlo por medio de un script php

Cuando resuelvas tu problema nos cuentas como fue.

Saludos.
  #4 (permalink)  
Antiguo 07/10/2005, 01:00
 
Fecha de Ingreso: febrero-2004
Ubicación: España. Madrid
Mensajes: 454
Antigüedad: 13 años, 9 meses
Puntos: 0
una pregunta tonta...
en los campos fisicamente se pueden guardar imagenes no? (dentro de la bbdd, no guardar la ruta hacia ella)
se podrian guardar igualmente tambien pdf´s (en la bbdd) en un campo blob no?
no se si habría limitacion de tamaño, o si es una gilipollez hacerlo, pero se puede no?
  #5 (permalink)  
Antiguo 07/10/2005, 02:55
Avatar de damargon  
Fecha de Ingreso: junio-2003
Ubicación: Madrid
Mensajes: 386
Antigüedad: 14 años, 5 meses
Puntos: 3
Gracias por vuestras respuestas.

Estoy utilizando el siguiente script sacado de php.net:

<?php
function dl_file($file){

//First, see if the file exists
if (!is_file($file)) { die("<b>404 File not found!</b>"); }

//Gather relevent info about file
$len = filesize($file);
$filename = basename($file);
$file_extension = strtolower(substr(strrchr($filename,"."),1));

//This will set the Content-Type to the appropriate setting for the file
switch( $file_extension ) {
case "pdf": $ctype="application/pdf"; break;
case "exe": $ctype="application/octet-stream"; break;
case "zip": $ctype="application/zip"; break;
case "doc": $ctype="application/msword"; break;
case "xls": $ctype="application/vnd.ms-excel"; break;
case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
case "gif": $ctype="image/gif"; break;
case "png": $ctype="image/png"; break;
case "jpeg":
case "jpg": $ctype="image/jpg"; break;
case "mp3": $ctype="audio/mpeg"; break;
case "wav": $ctype="audio/x-wav"; break;
case "mpeg":
case "mpg":
case "mpe": $ctype="video/mpeg"; break;
case "mov": $ctype="video/quicktime"; break;
case "avi": $ctype="video/x-msvideo"; break;

//The following are for extensions that shouldn't be downloaded (sensitive stuff, like php files)
case "php":
case "htm":
case "html":
case "txt": die("<b>Cannot be used for ". $file_extension ." files!</b>"); break;

default: $ctype="application/force-download";
}

//Begin writing headers
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");

//Use the switch-generated Content-Type
header("Content-Type: $ctype");

//Force the download
$header="Content-Disposition: attachment; filename=".$filename.";";
header($header );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$len);
@readfile($file);
exit;
}

dl_file("archivo1.zip");
//Llamo a la función así, y al tener el archivo en el mismo directorio me lo abre sin problemas:

//Pero al llamarlo así no lo encuentra, no debe de admitir rutas absolutas:
dl_file("/home/httpd/vhosts/midominio.com/tmp/archivo1.zip");

?>


¿Cómo puedo indicarle dónde está el archivo estando éste fuera de la ruta de la página?

Gracias!!

  #6 (permalink)  
Antiguo 07/10/2005, 09:12
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 15 años, 11 meses
Puntos: 126
Cita:
cyborg
una pregunta tonta...
en los campos fisicamente se pueden guardar imagenes no? (dentro de la bbdd, no guardar la ruta hacia ella)
se podrian guardar igualmente tambien pdf´s (en la bbdd) en un campo blob no?
no se si habría limitacion de tamaño, o si es una gilipollez hacerlo, pero se puede no?
Si se puede ..

Tienes un ejemplo en este mensaje-tutorial:
http://www.forosdelweb.com/f18/tutorial-ejemplo-subir-archivos-bd-guardando-bd-binario-127775/

Un saludo,
  #7 (permalink)  
Antiguo 07/10/2005, 09:14
 
Fecha de Ingreso: junio-2004
Mensajes: 51
Antigüedad: 13 años, 5 meses
Puntos: 0
El tema es que le deberias de agregar a esta funcion la carpeta ya que no contempla eso , aca : function dl_file($file), podrias agregar function dl_file($carpeta,$file)
en la comprobacion si existe el archivo seria:
if (!is_file($carpeta."/".$file)) { die("<b>404 File not found!</b>"); }

//Gather relevent info about file
$len = filesize($carpeta."/".$file);
$filename = basename($carpeta."/".$file); (esto definiria el nombre solamente del archivo)
$file_extension = strtolower(substr(strrchr($filename,"."),1));

y al descargar :
@readfile($carpeta."/".$file);

con eso podrias tener el asi:
www.sitio.com/descarga.php
www.sitio.com/carpeta/archivo.zip (archivo a descargar)
y en carpeta un .htaccess con este contenido:

Action validacion /descarga.php
SetHandler validacion

Obiamente el acceso se debe hacer con sesiones.

Saludos y espero que te sea util.

Suerte LEO
  #8 (permalink)  
Antiguo 07/10/2005, 09:17
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 15 años, 11 meses
Puntos: 126
damargon

Si le quitas la @ delante de readfile() tal vez veas el problema que tienes. (y aquí nos lo indicas textual).

En principio readfile() y las otras funciones (filesize() ..etc) no tienen ningún problema para leer un archivo de una ruta absoluta (del servidor). Pero si que puede ser que tengas alguna restricción de PHP para acceder a archivos fuera de lo que defina "open_base_dir" (php.ini) u otras directivas que restringen a PHP por donde puede tomar archivos.

Un saludo,
  #9 (permalink)  
Antiguo 07/10/2005, 09:21
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 15 años, 11 meses
Puntos: 126
icemanfree

La función original dl_file() .. toma la ruta que le pases completa para entregar el archivo al buffer de salida de PHP (con readfile()) y luego toma sólo el nombre del archivo (con basename()) para hacer un par de cosas más: filtrar su extensión y así validar el archivo que puedes descargar y componer la cabecera HTTP correspondiente ($header="Content-Disposition: attachment; filename=".$filename.";";) para definir el "nombre" que se mostrará para descargar el archivo (el que te quedará una vez lo descargues).

Un saludo,
  #10 (permalink)  
Antiguo 07/10/2005, 12:59
Avatar de damargon  
Fecha de Ingreso: junio-2003
Ubicación: Madrid
Mensajes: 386
Antigüedad: 14 años, 5 meses
Puntos: 3
Gracias por vuestras respuestas icemanfree y cluster.

Me devuelve el error "404 File not found!", es decir, no encuentra el archivo al pasarle la ruta absoluta del server:
"/home/httpd/vhosts/midominio.com/tmp/archivo1.zip"
La carpeta tmp tiene el chmod en 0777.

La directiva open_base_dir la tengo "no value", debería de cambiarla?
  #11 (permalink)  
Antiguo 07/10/2005, 14:49
Avatar de damargon  
Fecha de Ingreso: junio-2003
Ubicación: Madrid
Mensajes: 386
Antigüedad: 14 años, 5 meses
Puntos: 3
Bueno, sigo haciendo pruebas:

He quitado la primera línea de la función:
if (!is_file($file)) { die("<b>404 File not found!</b>"); }
por que he leido en php.net que la función "is_file" devuelve false si los permisos de la carpeta son de un usuario distinto a los que está utilizándolo. De ahí que siempre me devolviese "false" constantemente dándome el error 404 file not found.

Ejecuto el script y me devuelve este error:
open_basedir restriction in effect. File(/home/httpd/vhosts/midominio.com/tmp/archivo1.zip) is not within the allowed path(s): (/home/httpd/vhosts/midominio.com/httpdocs:/tmp)

He puesto safe_mode en Off y open_basedir lo he puesto a /home/httpd/vhosts para abarcar todos los dominios.

Pues nada, no hay manera, me sigue devolviendo el error "open_basedir restriction in effect".

¿alguna idea o solución?

Última edición por damargon; 07/10/2005 a las 14:55
  #12 (permalink)  
Antiguo 07/10/2005, 16:49
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 15 años, 11 meses
Puntos: 126
parece que te faltó el / final? (al definir tu open_base_dir)

/home/httpd/vhosts/

Indica como pones tus rutas en dicha directiva ..

Un saludo,
  #13 (permalink)  
Antiguo 07/10/2005, 18:10
 
Fecha de Ingreso: febrero-2004
Ubicación: España. Madrid
Mensajes: 454
Antigüedad: 13 años, 9 meses
Puntos: 0
Cita:
Iniciado por Cluster
Si se puede ..

Tienes un ejemplo en este mensaje-tutorial:
http://www.forosdelweb.com/showthread.php?t=127775

Un saludo,
ya veo..... pero con que tamaño mas o menos de fichero deja de resultar "rentable" guardarlos en la bbdd
si son muy grandes igual no es interesante...
  #14 (permalink)  
Antiguo 08/10/2005, 03:42
Avatar de damargon  
Fecha de Ingreso: junio-2003
Ubicación: Madrid
Mensajes: 386
Antigüedad: 14 años, 5 meses
Puntos: 3
Cita:
Iniciado por Cluster
parece que te faltó el / final? (al definir tu open_base_dir)

/home/httpd/vhosts/

Indica como pones tus rutas en dicha directiva ..

Un saludo,
Al ponerlo sin la "/" al final lo que hago es dejar abierto que en todos los subdirectorios por debajo del último indicado en la directiva se pueden abrir archivos con php.

En esta página viene bien explicado:
http://www.phpbuilder.com/manual/features.safe-mode.php

Concretamente en este párrafo: "The restriction specified with open_basedir is actually a prefix, not a directory name. This means that "open_basedir = /dir/incl" also allows access to "/dir/include" and "/dir/incls" if they exist. When you want to restrict access to only the specified directory, end with a slash. For example: "open_basedir = /dir/incl/". "

¿No crees que será más sencillo meter los archivos .pdf en un BD Mysql y acceder a ellos a través de una página restringida con sesiones?

Me está quemando el tema de poner los archivos fuera del root del server.

Muchas gracias Cluster,

Saludos!!
  #15 (permalink)  
Antiguo 12/10/2005, 01:34
Avatar de damargon  
Fecha de Ingreso: junio-2003
Ubicación: Madrid
Mensajes: 386
Antigüedad: 14 años, 5 meses
Puntos: 3
¿No hay más sugerencias?
  #16 (permalink)  
Antiguo 12/10/2005, 06:01
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 15 años, 11 meses
Puntos: 126
Cita:
¿No crees que será más sencillo meter los archivos .pdf en un BD Mysql y acceder a ellos a través de una página restringida con sesiones?
Gestionarlo desde una BD como Mysql también plantea sus problemas .. tal vez no de acceso y restricciones de PHP .. pero si de rendimiento del sistema, tamaño de tus archivos .. cantidad de ellos.

Sería cosa de que lo pruebes en tu caso particular .. pero almacenar archivos de varios MBytes en Mysql y gestionarlos desde ahí se puede volver contraproducente.

Un saludo,

Última edición por Cluster; 12/10/2005 a las 06:08
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 1 personas (incluyéndote)




La zona horaria es GMT -6. Ahora son las 16:46.