InputStream не читает некоторые файлы из JAR - PullRequest
0 голосов
/ 05 июля 2018

Я создал JAR-файл для моего Javalin приложения, и код работает нормально. Однако чтение некоторых файлов ресурсов из JAR завершается неудачно с inputStream.available() == 0, но оно работает как раз для некоторых других файлов.

Следующие файлы должны быть доставлены в самый раз:

a/
|\
| +- a.txt
| +- b.js
| +- c.css
|
b/
 \
  +- d.png
  +- e.txt

Однако InputStream читает только файлы a/a.txt, a/b.js и b/e.txt. Для всех остальных файлов он ничего не возвращает, и available() == 0, но он работает, когда я не читаю файлы из JAR, а из извлеченного пути к классам (и я использую ClassLoader независимо от того, как выглядит среда выполнения лайк). Кроме того, размер файла не имеет значения, a/a.txt намного больше, чем a/c.css, поэтому я не знаю, что с этим делать.

Пример кода (как я уже сказал, я использую Javalin для HTTP-запроса / ответа, который обрабатывается в объекте ctx, и я также используя Apache Tika для определения MIME-типа запрашиваемых файлов, который работает как положено):

// Example, real path is (correctly) fetched from the Context (ctx) object
String path = "a/c.css";

ClassLoader classLoader = Thread.currentThread ().getContextClassLoader ();
InputStream inputStream = classLoader.getResourceAsStream (path);

String contentType = tika.detect (inputStream, path);
ctx.header ("Content-Type", contentType);

if (contentType.contains ("text") || contentType.contains ("script")) {
    InputStreamReader streamReader = new InputStreamReader (inputStream);
    BufferedReader reader = new BufferedReader (streamReader);

    String line;
    StringBuilder builder = new StringBuilder ();
    while ((line = reader.readLine ()) != null) {
        builder.append (line).append ("\n");
    }

    String result = builder.toString ();
    ctx.header ("Content-Length", String.valueOf (result.length ()));
    ctx.result (result);

    reader.close ();
} else {
    ctx.header ("Content-Length", String.valueOf (inputStream.available ()));
    ctx.result (inputStream);
}

Я что-то здесь упускаю или я делаю что-то не так?

1 Ответ

0 голосов
/ 05 июля 2018

Я подозреваю, что причиной может быть обнаружение MIME-типа. Во-первых, попробуйте пропустить это и посмотрите, решит ли это вашу проблему.

Вот мое подозрение: tika.detect() очевидно, что необходимо использовать байты из данного потока, чтобы иметь возможность обнаруживать что-либо. Метод javadocs утверждает, что он может сбросить поток, только если он поддерживает маркировку. Таким образом, вы должны убедиться, что markSupported() метод из InputStream, возвращенный classLoader.getResourceAsStream(), на самом деле возвращает true.

Если это не так, Тика может, например, потреблять все содержимое файла до тех пор, пока он не сможет быть уверен в типе файла, затем не сможет сбросить поток, и тогда вам ничего не останется отправить клиенту. В этом случае вам следует обернуть оригинальную InputStream в BufferedInputStream (которая добавляет функцию отметки / сброса) и использовать ее для tika и для отправки контента.


Кстати: вы действительно должны использовать попробовать с ресурсами , чтобы убедиться, что все входные потоки, потоковые читатели и буферизованные читатели закрыты даже при возникновении исключения.

...