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:
- Capturando la pantalla de un ordenador
- Guardando la captura de pantalla en un elemento con JavaScript
- Enviando la imagen copiada del clipboard al servidor con Ajax
1.0 Capturando la pantalla de un ordenador
Muchas distribuciones en Linux como Fedora ofrecen aplicaciones desde las cuales podemos realizar capturas de pantallas:
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:
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.
Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter