Как определить расширение от fileBytes - PullRequest
0 голосов
/ 05 марта 2020

Мое приложение позволяет пользователям загружать файлы. При создании заголовков я использую Tika для установки расширения, как показано ниже. Это прекрасно работает для PDF-файлов. Сбой для файлов DO C и EXCEL.

private HttpHeaders getHeaderData(byte[] fileBytes) throws IOException, MimeTypeException {
        final HttpHeaders headers = new HttpHeaders();

        TikaInputStream tikaStream = TikaInputStream.get(fileBytes);
        Tika tika = new Tika();
        String mimeType = tika.detect(tikaStream);
        headers.setContentType(MediaType.valueOf(mimeType));

        MimeTypes defaultMimeTypes = MimeTypes.getDefaultMimeTypes();
        String extension = defaultMimeTypes.forName(mimeType).getExtension();
        headers.add("file-ext", extension);

        return headers;
    }

Я вижу, что mimeType разрешен в "application / pdf" для файлов PDF, но разрешается в " application / x-tika-oo xml "для файлов Excel и Word, что является проблемой. Как я могу получить форматы Word (.docx) и Excel (xlx, xlsx), если у меня есть файл в байтах.

Почему это работает для PDF?

1 Ответ

0 голосов
/ 12 марта 2020

Резюме

Короткий ответ: Вы должны использовать детектор Тики с классом MediaType, а не MimeTypes.

Немного более длинный ответ: Даже это не получит Вы полностью, из-за того, как старые файлы MS-Office структурированы. Для них вы также должны проанализировать файлы и проверить их метаданные.

Термин «тип носителя» заменил термин «тип MIME» - см. здесь :

[RFC2046] указывает, что типы носителей (ранее известные как Типы MIME) и подтипы медиа будут назначаться и перечисляться IANA.

Office 97-2003

Когда Tika проверяет файлы Excel и Word 97-2003 с помощью своего детектора, она вернуть тип носителя application/x-tika-msoffice. Я предполагаю (возможно, неправильно), что это способ обработки группы типов файлов, когда детектор не может определить специфику c файла MS-Office 97-2003 на основе его анализа. Это похоже на application/x-tika-ooxml в вашем вопросе.

Ожидаемые результаты

На основе списка IANA здесь и списка Mozilla здесь это типы носителей, которые мы ожидаем получить для файлов следующих типов:

  • .pdf :: application / pdf
  • .xls :: application / vnd.ms-excel
  • .do c :: application / msword
  • .xlsx :: application / vnd.openxmlformats-officedocument.spreadsheetml.sheet
  • .docx :: application / vnd. openxmlformats-officedocument.wordprocessingml.document

Программа

В показанной ниже программе используются следующие зависимости Maven:

    <dependencies>
        <dependency>
            <groupId>org.apache.tika</groupId>
            <artifactId>tika-core</artifactId>
            <version>1.23</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tika</groupId>
            <artifactId>tika-parsers</artifactId>
            <version>1.23</version>
        </dependency>
        <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>javax.ws.rs-api</artifactId>
            <version>2.1.1</version>
        </dependency>
    </dependencies>

Программа (только для этой демонстрации - не готов к производству) показано ниже. В частности, обратите внимание на методы tikaDetect() и tikaParse().

import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.util.Set;
import java.util.HashSet;
import org.apache.tika.mime.MediaType;
import org.apache.tika.mime.MimeTypeException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.detect.Detector;
import org.apache.tika.detect.DefaultDetector;
import org.apache.tika.exception.TikaException;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.sax.BodyContentHandler;
import org.apache.tika.parser.ParseContext;
import org.xml.sax.SAXException;
import org.xml.sax.ContentHandler;

public class Main {

    private final Set<File> msOfficeFiles = new HashSet();

    public static void main(String[] args) throws IOException, MimeTypeException,
            SAXException, TikaException {
        Main main = new Main();
        main.doFileDetection();
    }

    private void doFileDetection() throws IOException, MimeTypeException, SAXException, TikaException {
        File file1 = new File("C:/tmp/foo.pdf");
        File file2 = new File("C:/tmp/baz.xlsx");
        File file3 = new File("C:/tmp/bat.docx");
        // Excel 97-2003 format:
        File file4 = new File("C:/tmp/bar.xls");
        // Word 97-2003 format:
        File file5 = new File("C:/tmp/daz.doc");
        Set<File> files = new HashSet();
        files.add(file1);
        files.add(file2);
        files.add(file3);
        files.add(file4);
        files.add(file5);

        for (File file : files) {
            try (BufferedInputStream bis = new BufferedInputStream(
                    new FileInputStream(file))) {
                tikaDetect(file, bis);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        for (File file : msOfficeFiles) {
            tikaParse(file);
        }
    }

    private void tikaDetect(File file, BufferedInputStream bis)
            throws IOException, SAXException, TikaException {
        Detector detector = new DefaultDetector();
        Metadata metadata = new Metadata();
        MediaType mediaType = detector.detect(bis, metadata);
        if (mediaType.toString().equals("application/x-tika-msoffice")) {
            msOfficeFiles.add(file);
        } else {
            System.out.println("Media Type for " + file.getName()
                    + " is: " + mediaType.toString());
        }
    }

    private void tikaParse(File file) throws SAXException, TikaException {
        Parser parser = new AutoDetectParser();
        ContentHandler handler = new BodyContentHandler();
        Metadata metadata = new Metadata();
        ParseContext context = new ParseContext();
        try (BufferedInputStream bis = new BufferedInputStream(
                new FileInputStream(file))) {
            parser.parse(bis, handler, metadata, context);
            tikaDetect(file, bis);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Media Type for " + file.getName()
                + " is: " + metadata.get("Content-Type"));
    }
}

Фактические результаты

Программа генерирует некоторые предупреждения и информационные сообщения. Если мы проигнорируем их для этого упражнения, мы получим следующие операторы печати:

Media Type for bat.docx is: application/vnd.openxmlformats-officedocument.wordprocessingml.document
Media Type for baz.xlsx is: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Media Type for foo.pdf is: application/pdf
Media Type for bar.xls is: application/vnd.ms-excel
Media Type for daz.doc is: application/msword

Они соответствуют ожидаемым типам официальных носителей (MIME).

...