domingo, 29 de marzo de 2009

Manual de PHP 68. PDF. Header´s y visualización

¿Qué es un header?

En un documento PHP se pueden incluir instrucciones que obliguen al navegador del cliente a comportarse de una manera determinada.

Esas instrucciones que dicen al navegador del cliente cómo tiene que comportarse, van contenidas en la header de la página y pueden resultar muy útiles como complemento de otras funciones.

Su nombre se debe a que han de ser –obligatoriamente– lo primero que ha de recibir el navegador en el momento de ser atendida su petición. El grado de exigencia de esta condición es tal que ni siquiera se permite que les preceda ni una línea en blanco.

¿Cómo colocar las cabeceras?

Los header han de colocarse de forma que sus contenidos sean lo primero que aparezca en la página que llega al cliente y eso significa que:

• No puede aparecer delante de un header ninguna etiqueta HTML ni ningún contenido de este tipo.

• Ni siquiera se permite que se les anteponga una línea en blanco.

Requieren muchísima atención y cerciorarse siempre de que la marca del comienzo del script PHP () esté siempre en la primera línea del documento, sin dejar líneas en blanco delante de ella.

Puede que te preguntes: ¿ha de ir también en la primera línea del script PHP?

La respuesta es esta: tienen que ir antes de la primera función que genere una salida hacie el navegador del cliente.

Intentaremos aclarar esta idea.

Los scripts PHP (lo contenido entre y ?>) se ejecutan en el servidor y de ellos sólo llegan al navegador del cliente los resultados de la ejecución (las salidas echo o print, por citar dos ejemplos).

Las cabeceras han de llegar al navegador antes que esas posibles salidas, lo cual no es óbice para que se puedan efectuar –antes de insertar las headers– procesos que no produzcan salidas de tipo print, echo, etcétera.

La sintaxis de algunas header varía en algunos casos –lo podemos ver en el ejemplo– según el protocolo que utilice el servidor. Lo habitual es que lo servidores utilicen uno de estos: HTTP/1.1 ó HTTP/1.0.

Para saber cuál utiliza nuestro servidor basta con visualizar el info.php y buscar la directiva SERVER_PROTOCOL.

Los diferentes haeder

En los ejemplos que aparecen en la columna de ejemplos final están comentadas algunas de las cabeceras que es posible insertar en los ficheros PHP.

Cabría añadir la siguiente:

header("Location:dirección")

Mediante este header se redirecciona el navegador a la URL (absoluta o relativa) que se indicada en el parámetro dirección.

Cuando el navegador recibe un header de este tipo realiza de forma automática la petición de la página indicada en él.

Otra funciones PDF

Existe una función muy útil para un montón de propósitos que PHP empezó a incluir a partir de la versión 4.0.5. Se trata de la función

$b=pdf_get_buffer($p)

Esta función recoge en una variable $b el contenido de un documento PDF -identificado por $p- pudiendo enviarlo al navegador directamente desde la memoria del servidor y que, por tanto, no necesita ser escrito ni almacenado en el servidor.

La utilización de esa función requiere una modificación en la sintaxis -respecto a la de los ejemplos anteriores- y el uso de dos funciones nuevas, que son:

$p=pdf_new()

que es la función que generará un identificador de recurso, distinto de los que hemos venido utilizando hasta ahora, ($p) para el nuevo fichero PDF y que debe insertarse delante de:

pdf_open_file($p)

que abriría un fichero pdf en memoria.

Como observarás esta sintaxis difiere de la que hemos venido utilizando hasta ahora y que era la siguiente:

$f = fopen(nombre, "w");
$g = pdf_open($f)

Con esta sintaxis, creábamos (mediante la función fopen) un documento en el servidor y su identificador de recurso ($f); luego, creabámos un segundo identificador de recurso $g – por medio de pdf_open– que asociábamos con el anterior para que los resultados de las funciones pdf se fueran escri- biendo en el fichero abierto con la primera instrucción.

Ahora no necesitamos crear ningún documento y bastará con un solo identificador de recurso, que es, la salida de la función pdf_new.


Utilización de header


En este ejemplo se utilizan algunas header e incluimos como comentarios las utilidades de cada una de ellas

<?
#esta variable recoge el nombre del fichero a visualizar
$fichero="ejemplo132.pdf";
#esta función determina la longitud en bytes del fichero
$len = filesize($fichero);
/* esta cabecera -válida para HTTP/1.1- ordena al navegador
que no permita guardar la página
que no permita que se almecene en la caché del cliente*/
header("Cache-Control: no-store, no-cache, must-revalidate");
/* esta otra cabecera -válida para HTTP/1.0
indica al navegador que no guarde la página en la caché del cliente
he puesto ambas opciones para cubrir todo el especto probable */
header("Pragma: no-cache");
/* esta cabecera especifica al navegador el contenido
que va a recibir que en este caso no sería otra cosa
que algo que requiere una aplicacion capaz de interpretar
ficheros pdf */
header("Content-type: application/pdf");
/* como la norma de los headers establece que
siempre que se conozca el tamaño del contenido enviado
se incluya en la cabecera ese contenido, pues...
incluimos el tamaño ya que "filesize" nos midió el fichero
y guardo esa medida en la variable $len...
pero... fue posible utilizar esa función antes de las header
porque esa medida no fue mandada a la salida...
si hubiéramos escrito antes de los header... algo así como
Echo $len; ... la habríamos fastidiado...
ya habríamos tenido error en las cabeceras...*/
header("Content-Length: $len");
/* con esta otra header indicamos ls forma de presentación de
el contenido del documento... permite dos posibilidades
inline (la que he puesto aquí) o
attachment (que seria como fichero anexo)
fijate que en este "header" he puesto en filename un nombre distinto
del que tenía el fichero original... eso no tiene importancia
solo será el nombre con el que se guardará en la caché del cliente
en el caso de que no hubiéramos incluido la cabecera "no cache"
que dicho sea de paso... la he puesto aquí como ejemplo
pero que serían absolutamente innecesarias para este ejemplo
de visualización del documento */
header("Content-Disposition: inline; filename=felipe.pdf");
/* ya se acabaron las cabeceras del documento
aquí le decimos al servidor que lea el fichero y lo envie
al navegador del cliente... este ya lo interpretará
siguiendo las especificaciones que le hemos incluido
las cabeceras....*/
readfile($fichero);
?>



Visualización ficheros PDF creados en memoria

<?
# Creamos el PDF con las nuevas funcionesn>
$g = PDF_new();
pdf_open_file($g);
# A partir de aquí todo es igual a los ejemplos anteriores
pdf_begin_page($g, 595, 842);
$imagen1 = pdf_open_jpeg($g, "./images/cruz.jpg");
$h=0.5;
$v=0.8;
pdf_save($g);
$x1 = pdf_get_value($g, "imagewidth", $imagen1);
$y1 = pdf_get_value($g, "imageheight", $imagen1);
pdf_scale($g,$h,$v);
pdf_place_image($g, $imagen1, ((595/$h-$x1)/2), (842/$v-$y1), 1.0);
pdf_close_image ($g,$imagen1);
pdf_restore($g);
pdf_save($g);
$imagen2 = pdf_open_gif($g, "./images/cruz.gif");
$ancho=150;
$alto=325;
$x1 = pdf_get_value($g, "imagewidth", $imagen2);
$y1 = pdf_get_value($g, "imageheight", $imagen2);
$h=$ancho/$x1;
$v=$alto/$y1;
pdf_scale($g,$h,$v);
pdf_place_image($g, $imagen2, ((595/$h-$x1)/2), 200, 1.0);
pdf_close_image ($g,$imagen2);
pdf_restore($g);
PDF_end_page($g);
pdf_close($g);

# Después del pdf_close empezamos la lectura del buffer
$buffer = PDF_get_buffer($g);
/* Esta porción de código es idéntica a la del ejemplo anterior
con la única diferencia que ahora medimos la longitud de la cadena
buffer en vez de la longitud de un fichero como hacíamos allí */
$len = strlen($buffer);
Header("Content-type: application/pdf");
Header("Content-Length: $len");
Header("Content-Disposition: inline; filename=loquesea.pdf")
;
# Escribimos en el documento que se enviará al cliente
# el contenido de la cadena buffer
echo $buffer;
/* liberamos la memoria que contenía el fichero
con lo cual el documento solo aparecerá en el navegador del cliente
y en la caché de este (con el nombre loquesea.pdf).
Si no queremos que se almacene en la caché sería solo cuestión de
incluir las cabeceras no caché del ejemplo anterior */
pdf_delete($g);
?>



Una opción alternativa


En el caso de que no sea posible utilizar las funciones anteriores por incompatibilidad de versiones PHP o de las propias librerías PDF, se puede recurrir a un truco. Se trata de escribir el fichero PDF en servidor, enviarlo al cliente y, posteriormente, borrarlo. Ello serviría, al menos, para economizar espacio de almacenamiento en el servidor.

<?
# creo un fichero de la misma forma que
# lo hacíamos en ejemplo de páginas anteriores
$filename="leocadio.pdf";
$f = fopen($filename, "w");
$g = pdf_open($f);
pdf_begin_page($g, 595, 842);

/* aqui insertaríamos el código
para la generación del pdf.
En este caso lo cerramos en blanco */

PDF_end_page($g);
pdf_close($g);

# cerramos el fichero leocadio.pdf
fclose($f);
/* ahora insertamos exactemente el codigo
del primer ejemplo de esta página.
Fijate que pese a haber escrito un montón de código
aun estamos a tiempo de insertar las funciones de cabecera
ya que NO HE ENVIADO AUN NINGUNA SALIDA AL NAVEGADOR
eso sí, no olvides que delante de <? no puede haber
ninguna linea en blanco...*/
$len = filesize($filename);
header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline; filename=felipe.pdf");
readfile($filename)
;
/* ahora que ya he enviado
el contenido del fichero pdf al navegador
ya puedo borrar el fichero del servidor

unlink($filename);
/* como habrás observado
se trata de una chapuza en tres actos
1º.- Cramos el fichero en el servidor y lo cerramos
2º.- Leemos el contenido del fichero
3º.- Borramos el fichero del servidor */
?>






Fuente:


1 comentario:

Anónimo dijo...

Muy bueno el manual, felicidades.