Gracias a la librería html2pdf.js se puede crear un PDF en el navegador web usando solo JavaScript. En mi blog te enseñé a descargar ese PDF, pero ahora te enseñaré otra cosa: cómo enviar ese PDF a un servidor con PHP.
Vamos a combinar varias cosas, ya que el PDF también va a llevar una firma manuscrita. Veremos:
- Cómo solicitar la firma del usuario
- Enviar esa firma adjunta en el PDF
- Subir el PDF a PHP
Para esto, te recomiendo leer:
- Generando un PDF desde JS con html2pdf.js
- Obtener PDF de html2pdf.js y jsPDF como Blob
- Subir Blob de JS a PHP
- Solicitar firma de usuario con Canvas y JavaScript
Comencemos.
Diseño HTML
Además de importar las librerías y scripts de JavaScript, en el cuerpo del documento estarán los siguientes campos:
<input type="text" id="id" placeholder="ID">
<input type="text" id="nombre" placeholder="Nombre">
<input type="text" id="apellido" placeholder="Apellido">
<input type="text" id="direccion" placeholder="Dirección">
<p>Firma:</p>
<canvas id="canvas"></canvas>
<br>
<button id="btnLimpiar">Limpiar</button>
<button id="btnCrearPdf">Crear PDF</button>
Tenemos varios input para los datos del usuario, el canvas y los botones que sirven para limpiar el canvas y para crear el PDF.
Firma
El canvas o lienzo incrustado para que el usuario pueda colocar su firma en el documento PDF va a enviarse tal y como si fuera una imagen.
Por simplicidad, no explicaré cómo tomar la firma pues ya lo expliqué en otro tutorial, pero no te preocupes, ya que todo estará junto en el código completo de mi GitHub.
Ocultando botones
El PDF generado debe estar libre de los botones que limpian el canvas y crean el PDF. Para ello, al momento de generar el PDF, los botones son ocultados:
$ocultables.forEach($ocultable => {
$ocultable.style.display = "none";
})
Después, para mostrarlos, se establece la propiedad display
de style
en inline
.
Nota: $ocultables
son un arreglo de botones que fueron recuperados con querySelector
.
Generando PDF
Lo que sigue a continuación es generar el PDF a partir del HTML que tenemos, usando JavaScript y la librería html2pdf.js. La generación queda como se ve en el siguiente código.
Presta atención a que estoy esperando a que se resuelva la promesa que devuelve output
para tener el PDF como Blob en la variable pdfComoBlob
:
const $elementoParaConvertir = document.body; // <-- Aquí puedes elegir cualquier elemento del DOM
const pdfComoBlob = await html2pdf()
.set({
margin: 1,
filename: 'documento.pdf',
image: {
type: 'jpeg',
quality: 0.98
},
html2canvas: {
scale: 3, // A mayor escala, mejores gráficos, pero más peso
letterRendering: true,
},
jsPDF: {
unit: "in",
format: "a3",
orientation: 'portrait' // landscape o portrait
}
})
.from($elementoParaConvertir)
.output("blob");
Ahora que tenemos los bytes del PDF o el PDF “crudo” podemos enviarlo al servidor de PHP usando fetch
y FormData
.
Subir PDF generado con JavaScript a PHP incluyendo firma
Creamos un FormData
, adjuntamos los datos de los input así como el Blob del PDF y lo enviamos a recibir.php
cuyo código veremos más adelante.
El código para subir el PDF a PHP queda así:
const formData = new FormData();
formData.append("pdf", pdfComoBlob);
formData.append("id", $id.value);
formData.append("nombre", $nombre.nombre);
formData.append("apellido", $apellido.apellido);
formData.append("direccion", $direccion.direccion);
//formData.append("otraVariable", "otroValor"); // En PHP la recuperamos como $_POST["otraVariable"]
const respuestaHttp = await fetch("./recibir.php", {
body: formData,
method: "POST",
});
const respuestaDelServidor = await respuestaHttp.text();
La función append
de FormData
toma como primer argumento una clave. Si el valor (segundo argumento) es un archivo, entonces estará en $_FILES en el lado de PHP, accediendo a él como $_FILES["claveUsadaEnFormData"]
y si es un valor primitivo estará en $_POST["claveUsadaEnFormData"]
.
Fíjate que estoy esperando la respuesta del servidor como texto. Dicha respuesta será lo que el script de PHP (recibir.php
) imprima ya sea con echo
, printf
, etcétera.
Recibir PDF con PHP
Es momento de recibir el PDF que trae la firma (como imagen) y los datos del usuario, todo generado con JavaScript. El código mostrado a continuación se encuentra en el archivo recibir.php
.
El script es realmente sencillo, lo que hace es leer la variable id
enviada desde el cliente y nombrar así el PDF, colocando todo en un directorio llamado firmas
:
<?php
if (
!isset($_POST["id"]) ||
!isset($_POST["nombre"]) ||
!isset($_POST["apellido"]) ||
!isset($_POST["direccion"]) ||
!isset($_FILES["pdf"])
) {
exit("Faltan datos");
}
$archivoPdf = $_FILES["pdf"];
$id = $_POST["id"];
# Aquí podemos acceder a $_POST["nombre"], apellido, direccion
$directorio = "firmas";
if (!file_exists($directorio)) {
mkdir($directorio);
}
$nombre = $id . ".pdf";
$ubicacion = $directorio . DIRECTORY_SEPARATOR . $nombre;
move_uploaded_file($archivoPdf["tmp_name"], $ubicacion);
echo "OK";
Para guardar el PDF se utiliza la función move_uploaded_file
, misma que tiene que ver con la subida de archivos a PHP.
Más información
Solo quiero remarcar que podemos enviar cualquier cantidad de variables y archivos a PHP desde JavaScript, invocando a la función append
del FormData cuantas veces sea necesario.
Si quisiéramos mostrar los valores del input en el PDF, en lugar de los input, podríamos colocar un párrafo y llenarlo tomando su valor del input antes de generar el documento, así como ocultando los input de manera similar a como lo hacemos con los botones. Todo esto con JavaScript.
El script de PHP puede devolver cualquier información y en cualquier formato. Yo he elegido devolverla como texto plano.
Poniendo todo junto
El código completo lo dejaré en mi GitHub. Vas a necesitar PHP con Apache o un servidor parecido. Basta con colocar el código en la carpeta pública, acceder a index.html
y probar el código.
Recuerda que, en el lado de PHP, vas a necesitar permisos para escribir archivos. Esto depende de tu servidor, proveedor de servicios y configuración en general.