sábado, 8 de octubre de 2011

Apache Tika 1.0. Un ejemplo de uso.

Apache tika 1.0



Apache tika por fin llega a su versión 1.0.
Es uno de los tantos proyectos surgidos a partir de lucene, en su caso particular, su objetivo es extraer metadatos de los archivos.

La lista de archivos soportados es muy amplia y variada.
En lo personal actualmente lo utilizo (entre otras cosas) para implementar un pequeño filtro para los archivos recibidos en una aplicación web.

Es común que, cuando nuestra aplicación requiera recibir archivos por un upload, tengamos que agregar mecanismos de validación ya sea por tamaño o tipo de archivo (¿no queremos que nos suban un sh o algo similar cierto?).

Una primera validación puede basarse en validar la extención del archivo, pero, seamos sinceros, todos hemos cambiado la extención de un archivo para brincarlos validaciones ;)
-Durante mucho tiempo (y a causa de un sistema dónde supe que ya casi nadie esa esa extención) mis archivos de música y video obscuros tenían extención .tiff -

Entonces, debemos usar algo mucho más fiable, una segunda propuesta es validar la cabecera del archivo y así ir descifrando que tipo de archivo es.

Pero, los libros lo dicen claramente: no debemos re-inventar la rueda.

Apache tika, entre otras cosas permite obtener esa información.

A continuación implementaremos un sencillo método para validar que tipo de archivo estamos recibiendo.

El primer paso es agregar los imports requeridos:

import java.io.*;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.BodyContentHandler;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
Nuestro método principal es uno que recibe un byte[] y un String con el mime-type sobre el cual queremos comparar (el trim es el sello de la casa):

public static boolean isMimeType(byte[] b, String mime) throws
IOException,
SAXException,
TikaException {
boolean res = false;
InputStream is = new ByteArrayInputStream(b);

ContentHandler contenthandler = new BodyContentHandler();
Metadata metadata = new Metadata();
metadata.set(Metadata.RESOURCE_NAME_KEY, "temporal");
Parser parser = new AutoDetectParser();
// OOXMLParser parser = new OOXMLParser();
parser.parse(is, contenthandler, metadata);
if (mime.trim().toLowerCase().equals(
metadata.get(Metadata.CONTENT_TYPE).trim().toLowerCase()))
{
res = true;
}
return res;
}
Nuestro método requiere un arreglo de bytes, asumiendo que así es como recibimos el archivo, pero, con este otro método podemos tomarlo desde de un File:
private static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
long length = file.length();
if (length > Integer.MAX_VALUE) {
// File is too large
}
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length &&
(numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)
{
offset += numRead;
}
if (offset < bytes.length) {
throw new IOException("Could not completely read file "
+ file.getName());
}
// Close the input stream and return bytes
is.close();
return bytes;
}
Con esos método, es fácil poder hacer lo siguiente:
// ¿Será un pdf?
System.out.println(
MimeUtil.isMimeType(
MimeUtil.getBytesFromFile(
new
File("/Users/aldebaran/carpeta1/documentos/archivo1.pdf")
),
"application/pdf")
);
Si nuestro archivo es un pdf, así tenga otra extención, el resultado será:
true

Y listo.... tenemos un sencillo filtro de archivos conociendo su mime-type a través de apache-tika.

Saludos...
---
RuGI

3 comentarios:

  1. Buenas noches, me gustaría saber si puede poner un ejemplo de extracción de texto especifico de un pdf con apache tika, si no es mucha molestia, o si tuviera documentación al respecto me la pudiera compartir, agradeciéndole la atención solo me queda felicitarle y agradecerle el compartir su conocimiento con todos nosotros

    ResponderEliminar
  2. Hola..

    Tika esta diseñado para extraer metadatos de los archivos, si lo que requieres es extraer el texto de un pdf... quizà te sea de màs utilidad: PDFBOX
    http://pdfbox.apache.org/userguide/cookbook.html

    Saludos!!!

    ResponderEliminar
    Respuestas
    1. Hola que tal, si mira lo que pasa es que es para un proyecto escolar y se me pidio imperativamente usar apache tika, leyendo sobre esta api veo que implementa las funcionalidades de pdfbox en su pdfparser, mi duda es, debido a que solo lo estoy empezando a ver teoricamente, si haciendo una instancia del pdfParser de tika puedo usar las clases, metodos y atributos del pdfbox, ya que con tika se pueden inyectar metadatos para hacer extracción especifica de algunos datos del documento no todo el texto, espero haberme echo entender, la verdad que si ando algo confundido debido a que es un tema nuevo para mi... saludos

      Eliminar