Obteniendo una captura de pantalla del portapapeles (clipboard) con JavaScript

29-01-2015 - Andrés Cruz

Obteniendo una captura de pantalla del portapapeles (clipboard) con JavaScript In english

Este material forma parte de mi curso y libro completo; puedes adquirirlos desde el apartado de libros y/o cursos.

Ver ejemplo Descargar fuente

En esta entrada veremos como copiar una imagen producto de una captura de pantalla que se encuentre guardada de manera temporal en el portapapeles o clipboard en un elemento <img>.

Además veremos como podemos enviar esta imagen a través de Ajax para su procesamiento y guardado en el servidor; a continuación, la tabla de contenido:

  1. Capturando la pantalla de un ordenador
  2. Guardando la captura de pantalla en un elemento con JavaScript
    1. El evento paste en JavaScript
    2. Definiendo nuestra función para capturar el evento
    3. Explicando la función anterior…
  3. Enviando la imagen copiada del clipboard al servidor con Ajax
    1. Guardando la imagen en el servido
    2. Generando un string codificado en base64 de la imagen en el servidor
    3. ¿Cómo guardar la imagen en base64 en nuestra base de datos?

1.0 Capturando la pantalla de un ordenador

Muchas distribuciones en Linux como Fedora ofrecen aplicaciones desde las cuales podemos realizar capturas de pantallas:

captura de pantalla aplicación

Que permiten guardar una imagen producto de la captura de pantalla en alguna ubicación en la computadora o en el portapapeles; este último es parte de nuestro caso de interés.

También se pueden usar la tecla F12 o la tecla ImprPant provista en muchos teclados; aunque es posible que estas acciones no copien la imagen en el portapapeles o inclusive que no funcionen en determinados sistemas operativos.

2.0 Guardando la captura de pantalla en un elemento <img> con JavaScript

Una vez que nos hayamos hecho con la captura de pantalla en el portapapeles, debemos definir un evento que permita capturar el momento cuando copiamos algún contenido en un sitio web mediante:

  • La combinación Ctrl + V en nuestro teclado.
  • La seleccionando la opción paste/pegar desde nuestro navegador.
  • El menú emergente, presionamos sobre la opción paste/pegar.

Más información en la w3schools.

2.1 El evento paste en JavaScript

La API de JavaScript provee un evento que permite capturar el evento paste/pegar a través de la siguiente línea de código:

window.addEventListener("paste", pasteEvent);

2.2 Definiendo nuestra función para capturar el evento

Ahora podemos definir la función llamada pasteEvent() que se ejecutará cuando ocurra alguno de los eventos mencionados anteriormente; dicha función permite copiar el contenido del portapapeles en un elemento de tipo <img>; veamos la definición completa de la función:

          window.addEventListener("paste", processEvent);

            function processEvent(e) {

                for (var i = 0; i < e.clipboardData.items.length; i++) {
                    // get the clipboard item
                    // obtengo el clipboard item
                    var clipboardItem = e.clipboardData.items[0];
                    var type = clipboardItem.type;

                    // verifico si es una imagen
                    if (type.indexOf("image") != -1) {

                        // obtengo el contenido de la imagen BLOB
                        var blob = clipboardItem.getAsFile();
                        console.log("blob", blob);
                        // creo un la URL del objeto
                        var blobUrl = URL.createObjectURL(blob);
                        console.log("blobUrl", blobUrl);
                        // agrego la captura a mi imagen
                        document.getElementsByTagName("img")[0].setAttribute("src", blobUrl);

                    } else {
                        console.log("No soportado " + type);
                    }
                }
            }

2.3 Explicando la función anterior…

ClipboardEvent.clipboardData para leer los datos del portapapeles

El objeto clipboardData permite acceder en modo sólo lectura a la data contenida en el portapapeles a través de un Array de items; También podemos encontrar el tipo de datos (el cual puede ser texto, imágenes, etc) que se encuentra en una posición determinada del Array.

var clipboardItem = e.clipboardData.items[i];

Una vez que tengamos el item a evaluar; determinamos el tipo de data y la data almacenada respectivamente:

  • Consultamos el tipo a través del método type type.indexOf("image").
  • Obtenemos la data BLOB (raw data) a través del método getAsFile() clipboardItem.getAsFile().

Luego de inspeccionar el tipo de data y obtenida la misma, es necesario convertir la data de un objeto BLOB a un DOMString empleando el método createObjectURL() que crea una URL que representa el objeto, para que la imagen pueda ser reenderizada en un elemento de tipo <img>:

var blobUrl = URL.createObjectURL(blob);  

Finalmente copiamos el contenido de la imagen proveniente de la captura de pantalla en un elemento <img>:

img.attr("src", blobUrl);

2.4 Resultado final del experimento

Copia la imagen que tengas en el portapapel con Ctrl + V u otra modalidad.

3. Enviando la imagen copiada del clipboard al servidor con Ajax

3.1 Guardando la imagen en el servidor

Un uso útil del experimento presentado anteriormente consiste en poder guardar la imagen ya generada y guardada en un elemento <img> en el servidor; para esto podemos emplear Ajax o un formulario de la manera tradicional; aunque antes de poder guardar la imagen en el servidor debemos procesarla para que pueda ser manejada correctamente.

3.2 Generando un string codificado en base64 de la imagen en el servidor

Llegado a este punto, si verificamos el atributo source src de la imagen:

src img

Nos daremos cuenta que no es más que un valor que representa nuestra imagen, más no nos ofrece ninguna información sobre la misma; para poder guardar una imagen en el servidor no es posible emplear un tipo BLOB o la URL que lo represente; debemos de codificar la misma en base64 para que la imagen pueda ser procesada fácilmente desde el servidor.

Podemos convertir nuestra imagen fácilmente de un tipo BLOB a base64 con el siguiente script:

            var reader = new window.FileReader();
            reader.readAsDataURL(clipboardItem.getAsFile());
            
            reader.onload = function() {
                console.log(reader.result.replace('data:image/png;base64,', '')
                        .toString()
                $.ajax({
                    type: 'POST',
                    url: URL,
                    data: {
                        'pantalla': reader.result
                                .replace('data:image/png;base64,', '').toString(),
                    },
                    success: function(response) {}
            });
            }

El objeto FileReader()

Primero creamos un objeto de tipo FileReader() que permite leer archivos de manera asíncrona.

Una vez leído el archivo (nuestra imagen) la propiedad result para leer el contenido del archivo/imagen ya codificado en base64;.

Una vez codificada nuestra imagen, es posible enviar la imagen codificada en base64 por Ajax o a través de un campo en un formulario.

3.3 ¿Cómo guardar la imagen en base64 en nuestra base de datos?

Una vez obtenida nuestra imagen codificada en base64 en el lado del servidor se debe de decodificar la misma; si empleamos Java Web podemos usar la siguiente función para decodificar la imagen en base64 a un arreglo de byte:

byte imagen[] = Base64.decodeBase64(imageString);

En PHP existe una función similar:

$data = base64_decode($data);

Ya decodificada la imagen se puede guardar el base de datos como si se tratase de cualquier otro archivo obtenido en el servidor por un input de tipo file.

Consideraciones

Dependiente de la función empleada para decodificación a emplear puede ser necesario retirar la cabecera data:image/png;base64 presente en nuestra imagen codificada en base64; esto se aplica en para la función Base64.decodeBase64 en Java, en caso de dejarse esta cabecera la imagen podría decodificarse con errores y por lo tanto el archivo estaría corrupto.

Ver ejemplo Descargar fuente


Andrés Cruz
Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.

Conozca nuestros cursos sobre Laravel, CodeIgniter, Flutter, Electron, Django, Flask y muchos más!

Ver los cursos
¡Hazte afiliado en Gumroad!

!Cursos desde!

4$

En Academia

Ver los cursos

!Libros desde!

1$

Ver los libros
!Web Alojada en Hostinger!