Ir al contenido principal

Abrir imágenes de un archivo de Word con JSZip o PizZip

Dado a que un archivo .docx es en realidad un archivo ZIP compimido con todos los recursos del documento de Word, podemos descomprimir dicho archivo y extraer las imágenes.

En nuestra página web deberemos de disponer un objeto de imagen pero sin SRC:

<img id="idImagen" width="100%" />

Luego decidimos si damos la opción de descargar un archivo que se encuentre en un servidor, mediante la función fetch() de JavaScript, o mediante cargar desde un INPUT de tipo FILE. Para cualquiera de los dos casos, ejecutaremos una función fnLeerDocx() a la cual le pasaremos: a) El INPUT o el Blob generado por el Fetch, y b) Una función para cuando termine de procesarse el contenido binario generado por el archivo.

Para el caso del INPUT deberemos agregar:

a) <input type="file" id="idArchivoSubir" /><button id="idProcesar">Procesar</button>

Para el caso del Fetch tengamos a mano un INPUT para anotar la dirección y un botón para proceder con la descarga.

b) <input type="url" id="idArchivoDescargar" /><button id="idDescargar">Descargar el archivo</button>

Caso del INPUT

Agregamos un SCRIPT y ejecutamos lo siguiente:

<script>
idArchivoSubir.onchange = function() {
  fnLeerDocx( this, fnZipLeidoPorCompleto ) ;
}
</script>

Caso del FETCH

Agregamos un SCRIPT y ejecutamos lo siguiente:

<script>
idDescargar.onclick = function() {
  fetch( idArchivoDescargar.value )
    .then( x => x.blob() )
    .then( $contenido => {
      fnLeerDocx( $contenido, fnZipLeidoPorCompleto );
    })
  ;
}
</script>

La función fnLeerDocx()

Se compone por lo siguiente y se trata de utilizar el objeto Lector de Archivos (FileReader) de JavaScript. Éste debe abrir un objeto binario o Blob, proveniente del input de tipo FILE o del fetch. Una vez que lo abra creará una instancia de PizZip() apuntando al contenido y la guardará en una variable global (corregir para mejorar esto).

function fnLeerDocx( $objeto, $fn ) {

        var $lector = new FileReader();
        $lector.readAsBinaryString(
            $objeto instanceof HTMLElement
            ? $objeto.files.item(0)
            : $objeto
        );

        $lector.onerror = function($masInfo) {
          console.log('Error al leer el archivo', $masInfo);
        };

        $lector.onload = function($situacion) {
          var $contenido = $situacion.target.result;
          window.$zip = new PizZip($contenido);
          $fn();
        };

 }

La función fnZipLeidoPorCompleto()

Esta función se encarga de agregar los nombres de cada archivo de imagen recuperados del Zip leído. Ahora lo que agregaremos en el HTML es la posibilidad de tener una lista ampliada. Para ello agregamos un SELECT con atributo MULTIPLE para permitir este formato.

<select id="idArchivos" multiple></select>

La función se encargará de rellenarla con tantos objetos OPTION como imágenes tenga el archivo de Word. De tarea habrá que agregar que si no tiene imágenes se agregue un OPTION que informe de esto.

function fnZipLeidoPorCompleto() {    
   $archivos = window.$zip.files ;
   for( $cadaNombre in $archivos ) {
      if( $cadaNombre.includes(".png") )
         idArchivos.innerHTML
         += `<option>${ $cadaNombre }</option>`
      ;
   }
}

Finalmente, renderizar la imagen

Por último, tenemos que hacer algo para que al hacerle click al SELECT la imagen se actualice. Agregamos un escuchador de eventos ONDBLCLICK para esperar por algún doble click, y entonces se produce la magia.

Por cierto, el SRC del objeto IMG deberá estar en formato Base64 que es un formato de texto y no binario. Para que esto sea efectivo, el SRC debe comenzar con la expresión data:image/png;base64 y seguido una coma.

idArchivos.ondblclick = function() {
  $binario = $zip.files[ this.value ].asBinary() ;
  $base64 = btoa( $binario ) ;
  idImagen.src = "data:image/png;base64," + $base64 ;
}




Comentarios

Entradas populares de este blog

Probando ChatGPT - Mapa conceptual con Mermaid

 Había conversado con ChatGPT acerca de cuidado de las plantas e hidroponía. Luego de unos días me di cuenta que quizás también podría saber acerca de crear Mapas conceptuales. Salió lo siguiente; le falta un concepto para crear correctamente mapas conceptuales (la relación entre los conceptos), pero podría ser algo para ayudarnos a corregir mejor. El texto original era el que cito a continuación, pero le agregué explícitamente que me armara un "mapa conceptual" utilizando el lenguaje Mermaid, un lenguaje descriptivo que permite construir gráficos diversos, entre ellos Mapas conceptuales, generando un archivo SVG. ``` Hacé un mapa conceptual en lenguaje Mermaid con el siguiente texto, redactado anteriormente: "La hidroponía es un método de cultivo que se utiliza para cultivar plantas sin suelo utilizando una solución nutriente y agua. Algunas plantas pueden cultivarse con éxito mediante hidroponía, mientras que otras necesitan el suelo para crecer y prosperar. De las pl...

Conectar a Servidor Node.JS desde VB6 o VBA

El presente código sirve tanto para Visual Basic 6.0 (sí, todavía sirve, todavía sirve!) como para Visual Basic para Aplicaciones (Excel o VBA). ' Si estamos en Visual Basic para Aplicaciones agregar la referencia ' WinHTTP, en el menú Herramientas, Referencias, Microsoft WinHTTP Services Function Solicitar( _ ByVal URLBase As String _ , Optional ByVal Puerto As Integer = 80 _ , Optional ByVal Seccion As String = "" _ , Optional ByVal Metodo As String = "GET" _ ) As String On Error GoTo solucion #If VBA6 Then Dim objXML As New WinHttpRequest #ElseIf Win32 Then Dim objXML As Object Set objXML = CreateObject("MSXML2.ServerXMLHTTP") #End If objXML.Open Metodo, URLBase & ":" & Puerto & "/" & Seccion, False objXML.send If (objXML.Status = 404) Then Solicitar = "404 Error" Else Solicitar = objXML.responseText End If Se...