Screenshot de página web con PHP y JavaScript

Tomar screenshot de página web y enviarla a PHP usando html2canvas

Las capturas de pantalla de las aplicaciones web (o sitios web) son una forma bastante buena de arreglar errores de nuestros programas reportados por usuarios, ya que gracias a ellas podemos ver qué error aparece o cuál es el problema que reportan (sobre todo de diseño).

Screenshot de página web con PHP y JavaScript
Screenshot de página web con PHP y JavaScript

En el mundo de JavaScript existe la librería html2canvas cuyo uso ya vimos anteriormente, de hecho esto podría ser la continuación del mismo, en donde veremos cómo enviar una captura de pantalla a un servidor con PHP.

Aunque el ejemplo muestra cómo recibir la captura de la webapp con PHP, podemos adaptar el código para otros lenguajes del servidor.

¿Qué vamos a hacer?

Vamos a hacer una demostración para tomar una captura de una página web con html2canvas y después enviar la captura a un servidor con PHP.

Esta captura será enviada al hacer click en un botón, pero puede ser enviada incluso sin la acción del usuario (así que cuidado con los ataques XSS) en cualquier momento.

Puedes ver el código final y actualizado en mi GitHub. Por cierto, si quieres hacer esto con Node.JS ya he escrito el tutorial hace algún tiempo.

Requisitos y posts recomendados

A través del post veremos muchas cosas que ya he explicado a fondo en otros lugares.

El post más importante es en donde usamos html2canvas para tomar una captura de una página web pero sin enviarla a ningún lado, sino adjuntarla o guardarla localmente.

Aparte de eso, en JavaScript utilizo las backticks y funciones flecha, codifico con JSON y finalmente en PHP lo decodifico para escribir el contenido en un archivo.

Por cierto, también te recomiendo ver el tutorial para tomar una foto de la cámara web con JavaScript y enviarla a PHP.

Nota: si no tienes PHP mira este post para instalarlo, o este otro en donde lo instalamos sobre Android.

La página web

Es un sitio web con una imagen, una tabla y algo de contenido.

<!DOCTYPE html>
<html>

<head>
	<!--
		* Tomar screenshot de página web con html2canvas para enviarla a un servidor
		* web con PHP y guardarla como imagen
		* Visita: https://parzibyte.me/blog
		* 
		* @author parzibyte
	-->
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width">
	<title>Tomar captura de página web y enviarla a servidor web con PHP</title>
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css" />
</head>

<body>
	<!--
    El botón no aparece porque está fuera del div
  -->
	<br>
	<button class="button is-success" id="btnCapturar">Tomar captura</button>
	<!--
    En este caso le "tomamos" la foto al div. Podría ser a un div o 
    a cualquier elemento HTML
  -->
	<div id="contenedor">
		<h1 class="is-size-1">Tomar captura de pantalla con html2canvas y enviarla a servidor web con PHP</h1>
		<a href="//parzibyte.me/blog" target="_blank">By Parzibyte</a>
		<div class="notification is-primary">
			<p>Estamos probando la conversión de HTML a una imagen con html2canvas</p>
		</div>
		<table class="table is-bordered">
			<thead>
				<tr>
					<th>Nombre</th>
					<th>Versión</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td>KitKat</td>
					<td>4.4</td>
				</tr>
				<tr>
					<td>Lollipop</td>
					<td>5</td>
				</tr>
				<tr>
					<td>Marshmallow</td>
					<td>6</td>
				</tr>
				<tr>
					<td>Nougat</td>
					<td>7</td>
				</tr>
				<tr>
					<td>Oreo</td>
					<td>8</td>
				</tr>
				<tr>
					<td>Pie</td>
					<td>9</td>
				</tr>
			</tbody>
		</table>
		<img style="max-width: 100%;" src="cosmos-4112660_1280.jpg">
	</div>
	<!--
    Cargar el script de html2canvas, podría ser desde un servidor
    propio o como yo lo hago: desde jsdelivr
  -->
	<script type="text/javascript"
		src="https://cdn.jsdelivr.net/npm/html2canvas@1.0.0-rc.1/dist/html2canvas.min.js"></script>

	<!--
      Después de eso, cargar el script que contiene nuestra lógica
    -->
	<script src="script.js"></script>
</body>

</html>

Lado del cliente: tomar captura con JavaScript

En JavaScript le tomamos la foto al cuerpo completo; no ignoramos elementos ni capturamos otros elementos pero es totalmente posible como lo vimos en el post anterior.

La parte que cambia es que convertimos el canvas a imagen pero no la descargamos, sino que esa cadena en base 64 la enviamos a nuestro servidor usando AJAX a través de la función fetch.

/**
 * Tomar screenshot de página web con html2canvas para enviarla a un servidor
 * web con PHP y guardarla como imagen
 * Visita: https://parzibyte.me/blog
 * 
 * @author parzibyte
 */
//Definimos el botón para escuchar su click
const $boton = document.querySelector("#btnCapturar"), // El botón que desencadena
  $objetivo = document.body; // A qué le tomamos la foto

const enviarCapturaAServidor = canvas => {
  // Cuando se resuelva la promesa traerá el canvas
  // Convertir la imagen a Base64
  let imagenComoBase64 = canvas.toDataURL();
  // Codificarla, ya que a veces aparecen errores si no se hace
  imagenComoBase64 = encodeURIComponent(imagenComoBase64);
  // La carga útil como JSON
  const payload = {
    "captura": imagenComoBase64,
    "by": "Parzibyte",
    // Aquí más datos...
  };
  // Aquí la ruta en donde enviamos la foto. Podría ser una absoluta o relativa
  const ruta = "./api/guardar.php";
  fetch(ruta, {
    method: "POST",
    body: JSON.stringify(payload),
    headers: {
      "Content-type": "application/x-www-form-urlencoded",
    }
  })
    .then(resultado => {
      // A los datos los decodificamos como texto plano
      return resultado.text()
    })
    .then(nombreDeLaFoto => {
      // nombreDeLaFoto trae el nombre de la imagen que le dio PHP
      console.log({ nombreDeLaFoto });
      alert(`Guardada como ${nombreDeLaFoto}`);

    });
};

// Agregar el listener al botón
$boton.addEventListener("click", () => {
  html2canvas($objetivo) // Llamar a html2canvas y pasarle el elemento
    .then(enviarCapturaAServidor); // Cuando se resuelva, enviarla al servidor
});

Si te fijas, he usado JSON para enviar los datos, ahí puedes adjuntar más datos si lo requieres.

Recibir captura con PHP y guardar la imagen en un archivo

En el lado del servidor accedemos al cuerpo de la petición y lo decodificamos con JSON.

Quitamos el “data/image…” de la imagen si es que lo tiene, decodificamos con urldecode lo que codificamos con encodeURIComponent, la imagen en base 64 la decodificamos igualmente y llamamos a file_put_contents para guardar la imagen.

<?php
/**
 * Recibir screenshot tomada con html2canvas desde JavaScript
 * Visita: https://parzibyte.me/blog
 *
 * @author parzibyte
 */

$payload = json_decode(file_get_contents("php://input"));
if (!$payload) {
    exit("!No hay payload!");
}

$captura = $payload->captura;
$by = $payload->by;
// Aquí obtener más datos si existen...

// Quitar "data:image..." de la cadena
$capturaLimpia = str_replace("data:image/png;base64,", "", urldecode($captura));
//Venía codificada pero sólo la codificamos así para que viajara por la red,
//ahora la decodificamos y
//guardamos el contenido dentro de un archivo
$imagenDecodificada = base64_decode($capturaLimpia);

//Calcular un nombre único
// Nota: el nombre podría enviarse con la carga útil desde JS
$nombreImagenGuardada = "captura_" . uniqid() . ".png";
//Escribir el archivo
file_put_contents($nombreImagenGuardada, $imagenDecodificada);
echo $nombreImagenGuardada;

Finalmente imprimimos el nombre de la imagen guardada para que sea la respuesta que reciba JavaScript, y de nuevo lo digo, en la vida real podríamos enviar y recibir más cosas de acuerdo a las necesidades.

Conclusión

La combinación de JavaScript y PHP hace que nuestras apps tengan más funcionalidades sin importar su propósito.

En este ejemplo hemos visto cómo enviar una captura de pantalla a PHP, lo cual podríamos usar para recibir reportes de errores y ver exactamente lo que está pasando.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

2 comentarios en “Tomar screenshot de página web y enviarla a PHP usando html2canvas”

  1. Hola, muy bueno tu tu tuorial, copié los archivos tal cual como está en GitHub pero no me funciona, no le he modificado nada, qué podría estar pasando.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *