Início > Programação > Como Utilizar o Detector de Tipos de Arquivo do Apache Tika

Como Utilizar o Detector de Tipos de Arquivo do Apache Tika

O Tika é uma biblioteca da Apache que detecta e extrai metadados de diferentes tipos de arquivos. Já utilizei o Tika em dois projetos e tive pouco trabalho para configurar do jeito que eu precisava. No último projeto, eu precisava detectar se a extensão de um arquivo era xls ou xlsx.

Já vi muito código que apenas extraia a extensão à partir do nome do arquivo. Esses códigos vão desde simples parsers à partir do separador de extensão de arquivos até a utilização do FilenameUtils do Commons IO, que faz a mesma coisa. Porém, e se o arquivo não tiver extensão? E se alguém simplesmente alterar a extensão original do arquivo? Dependendo da sua regra de negócio, você poderia simplesmente invalidar arquivos sem extensão ou com extensão inválida, mas o Tika extrai as extensões do metadado, ou melhor, da assinatura do tipo do arquivo que está no próprio arquivo. Dessa forma, ele poderia até ser utilizado para análise forense computacional.

Nesse artigo, vamos demonstrar como utilizar o Apache Tika para determinar se um arquivo é uma planilha do tipo xls ou xlsx, que é uma extensão típica do MS-Office. Comecemos pelas dependências:

<dependency>
   <groupId>org.apache.tika</groupId>
   <artifactId>tika-core</artifactId>
   <version>1.14</version>
</dependency>
<dependency>
   <groupId>org.apache.tika</groupId>
   <artifactId>tika-parsers</artifactId>
   <version>1.4</version>
</dependency>
<dependency>
   <groupId>xerces</groupId>
   <artifactId>xercesImpl</artifactId>
   <version>2.11.0</version>
</dependency>

É importante observar que você deve utilizar a versão mais recente do xerces, pois algumas versões antigas estão levantando exceção ao tentar fazer parse de algum xml. Poderíamos utilizar diretamente os detectores do Tika, mas vamos fazer algo mais genérico. Vamos implementar um DirectoryStream.Filter[T], que é uma interface do java que permite decidir se um determinado arquivo deve ser aceito. O interessante é que nossa classe pode ser utilizada sozinha para testar o tipo de um arquivo ou pode ser combinada com filtros de diretório.

public class XLSFilter implements DirectoryStream.Filter<Path> {
   private Detector detector;
   private static final List<String> EXTENSIONS = Arrays.asList(".xls", ".xlsx");

   public XLSFilter() {
         List<Detector> detectors = new ArrayList<Detector>();
         /*
          * Detector especializado em analisar metadados do MS-Office.
          */
          detectors.add(new POIFSContainerDetector());
         /*
          * Detectores padrao.
          */
          detectors.add(MimeTypes.getDefaultMimeTypes());
         /*
          * Detector composto pelos detectores acima.
          */
          detector = new CompositeDetector(detectors);
    }

    @Override
    public boolean accept(Path path) throws IOException {
       BasicFileAttributes attrs = Files.readAttributes(path, 
          BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
       if (!attrs.isRegularFile()) {
          return false;
       }
       String extension = "";
       try {
          extension = detectarExtensao(path);
       } catch (MimeTypeException e) {
          e.printStackTrace();
       }
       return EXTENSIONS.contains(extension.toLowerCase());
   }

   private String detectarExtensao(Path path) 
         throws IOException, MimeTypeException {
      MediaType mediaType = detectarMediaType(path);
      TikaConfig config = TikaConfig.getDefaultConfig();
      MimeType mimeType = config.getMimeRepository().forName(mediaType.toString());
      return mimeType == null ? "" : mimeType.getExtension();
   }

   private MediaType detectarMediaType(Path path) 
          throws IOException, MimeTypeException {
       Metadata metadata = new Metadata();
       TikaInputStream inputStream = TikaInputStream.get(path);
       return detector.detect(inputStream, metadata);
   }
}

Agora, vamos utilizar nosso detector para filtrar arquivos em um diretório:

   Path folder = Paths.get(PATH_DIR).resolve(SUB_DIR);
   DirectoryStream.Filter<Path> filter = XLSFilter();
   DirectoryStream<Path> stream = Files.newDirectoryStream(folder, filter);
   for (Path path : stream) {
      System.ou.println(path.toFile().getName());
   }

Referências

1. [https://tika.apache.org/]
2. [http://www.programcreek.com/java-api-examples/index.php?api=org.apache.tika.mime.MediaType]

Anúncios
Categorias:Programação
  1. Nenhum comentário ainda.
  1. No trackbacks yet.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: