Pegar una imagen desde el portapapeles en #Genexus

Genexus tiene muchos componentes para potenciar nuestras aplicaciones, recientemente me solicitaron un sistema en el cual es necesario adjuntar archivos, todo era sencillo utilizando el componente Uploadify.

Pero como no todo es felicidad, me solicitaron que en el caso de imágenes con un simple “Print Screen” y un “ctrl + v” se lograra adjuntar la imagen.


Entonces comencé mi búsqueda por el Internet pensando inocentemente que ya habría alguna implementacion para realizar el pegado de una imagen desde el portapapeles(clipboard) para Genexus, pero grande fue mi decepción al no encontrar nada de información al respecto.


Ya que no encontré nada para hacerlo con Genexus, comence mi busqueda sobre una tecnologia en concreto, busque como hacerlo con JavaScript, en este caso encontre un codigo en la siguiente url http://joelb.me/blog/2011/code-snippet-accessing-clipboard-images-with-javascript/

En pocas palabras, el codigo espera el evento de pegado (ctrl + v) y en ese momento recorre el portapapeles en busca de una imagen, al encontrarla la guarda en una variable de imagen que se muestra en la pagina.

Para adecuar este codigo para ser utilizado junto a mi aplicacion Genexus, realice unos pequeños cambios.

Nota: Solo funciona en Firefox y Chrome

El siguiente codigo es del archivo javascript (portapapeles.js):

/* Manejo de los eventos paste */
function pasteHandler(e) {
// Necesitamos comprobar si event.clipboardData.items es soportado
//(Chrome)
if (e.clipboardData.items) {
// Obtenemos los items del portapapeles
var items = e.clipboardData.items;

if (items) {
// Recorremos todos los items, en busca de un tipo de imagen
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") !== -1) {
// Necesitamos representar la imagen como un
//archivo
var blob = items[i].getAsFile();
var reader = new FileReader();

reader.onloadend = function(event) {
var imgBase64 = reader.result.replace
('data:image/png;base64,', '');
document.forms["MAINFORM"].elements
["vIMAGENPORTAPAPELES"].value = imgBase64;
gx.evt.execEvt('E\'PEGA\'.',this);
};
reader.readAsDataURL(blob);// Blob to base64
}
}
}
// Si no podemos manejar los datos del portapapeles directamente
//(Firefox),
// necesitamos leer lo que fue pegado en el elemento contenteditable
} else {
// Este es un truco barato para asegurarnos que leeremos los datos
// despues de que hayan sido insertados.
pasteCatcher.focus();
setTimeout(checkInput, 50);
}
}

/* Analizamos la entrada en el elemento contenteditable */
function checkInput() {
// Guardamos el contenido pegado en una variable
var child = pasteCatcher.childNodes[0];
// Limpiamos el contenteditable para asegurarnos que siempre
// estamos recibiendo el ultimo contenido insertado
pasteCatcher.innerHTML = "";
if (child) {
// Si el usuario pega una imagen, el atributo src
// Representara la imagen como base64 encoded string.
if (child.tagName === "IMG") {
var imgBase64 = child.src.replace
('data:image/png;base64,', '');
document.forms["MAINFORM"].elements
["vIMAGENPORTAPAPELES"].value = imgBase64;
gx.evt.execEvt('E\'PEGA\'.',this);
}
}
}

function iniciaListener() {
// Se agrega el listener del evento paste
window.addEventListener("paste", pasteHandler);

// Comenzamos revisando que el navegador soporte
// el objeto Clipboard. Si no, es necesario crear un
// elemento contenteditable que atrape la imagen pegada
if (!window.Clipboard) {
pasteCatcher = document.createElement("div");
// Firefox permite pegar imagenes en elementos contenteditable
pasteCatcher.setAttribute("contenteditable", "true");
document.body.appendChild(pasteCatcher);
}
}
En lugar de mostrar la imagen en pantalla, la convierto a base64 y copio el resultado en una variable tipo longvarchar que se encuentra en el form, despues de esto lanzo el evento “PEGA” el cual se encarga de subir la imagen.

El codigo en Genexus

primero en el evento start agregamos el archivo javascript


Event Start
Form.JScriptSrc.Add( "portapapeles.js" )
EndEvent

Event 'Pega'
if not &ImagenPortapapeles.IsEmpty()
if not &NombreArchivo.IsEmpty()
&unblob.FromBase64String(&ImagenPortapapeles)
&SDTImgOTItem = new()
&SDTImgOTItem.OriginalFileName = 'Portapapeles.png'
&SDTImgOTItem.TemporalFileName = &unblob//.Substring
(6,&ImagenPortapapeles.Length())
&SDTImgOTItem.FileType = '.png'
&SDTImgOTItem.Eliminar = 0
&SDTImgOTItem.DescriptionFile = &NombreArchivo
&SDTImgOT.Add(&SDTImgOTItem)

&NombreArchivo.SetEmpty()
else
msg('Ingrese el titulo del archivo')
endif
endif
&ImagenPortapapeles.SetEmpty()
Endevent
En el evento “Pega” reviso que mi variable &ImagenPortapapeles no se encuentre vacía y la asigno a la variable tipo blob con el metodo FromBase64String, el cual convierte nuestro string en un archivo blob, despues guardo el blob en un sdt en el cual en listo los archivos adjuntos, al terminar recorro el SDT y muevo los archivos a mi servidor de archivos.

Si tienen alguna duda, que lo mas seguro es que asi sea, no duden en preguntar y contestare lo mas pronto que me sea posible, y con su ayuda editare la publicacion para que este mejor explicado.



Jesús Rodríguez

Consultor Genexus Senior - Scrum Master, Emprendedor, siguiendo mis sueños.

6 comentarios:

  1. Hola Colega, desde Caracas-Venezuela: estaba buscando un ejemplo de eso y me topé con tu información, podrías colocar un link con el xpz y así entender mejor lo que escribiste. Gracias por tu aporte. OJLM

    ResponderBorrar
    Respuestas
    1. Hola Oscar, por el momento no cuento con el ejemplo en xpz, pero estoy planeando dividir este post en 3 para poder explicarlo mejor y agregare los xpz de ejemplo. saludos

      Borrar
  2. Gracias Jesús. Infórmame cuando eso se produzca, pero que no sea el año que viene, jejejejeje.
    Saludos

    ResponderBorrar
  3. Hola Oscar, si bien esto es viejo, es vigente, gracias por compartirlo, lo estoy intentando usar en Gx16, net, chrome, y no me esta funcionando, desde Gx siempre tengo la var imagenportapapeles vacia. Tendras alguna idea ? Gracias

    ResponderBorrar
  4. Perdon, era para Jesus la pregunta.... ;)

    ResponderBorrar