2

我为我的Javalin应用程序构建了一个 JAR 文件,并且代码运行良好。但是,从 JAR 中读取一些资源文件失败并显示inputStream.available() == 0,但它适用于其他一些文件。

以下文件应正确交付:

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

但是,仅InputStream读取文件a/a.txt和. 对于所有其他文件,它什么都不返回,并且,但是当我不是从 JAR 中读取文件而是从提取的 Classpath 中读取文件时(并且无论执行环境是什么样的,我都在使用)。另外,文件大小无关紧要,比 大得多,所以我对此一无所知。a/b.jsb/e.txtavailable() == 0ClassLoadera/a.txta/c.css

一些示例代码(正如我所说,我将Javalin用于对象中正在处理的 HTTP 请求/响应,ctx并且我还使用Apache Tika来检测所请求文件的 MIME-Type,它按预期工作):

// 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);
}

我在这里遗漏了什么还是我做错了什么?

4

1 回答 1

1

我怀疑 MIME 类型检测可能是原因。首先,尝试将其排除在外,看看是否可以解决您的问题。

这是我的怀疑:tika.detect()显然需要消耗给定流中的字节才能检测到任何东西。方法 javadocs声明它只能在支持标记的情况下重置流。因此,您应该验证返回的markSupported()方法是否实际返回。InputStreamclassLoader.getResourceAsStream()true

如果没有,Tika 可能会消耗文件的所有内容,直到它可以确定文件类型,然后无法重置流,然后就没有任何东西可以发送给客户端了。在这种情况下,您应该将原件包装InputStream在 a 中BufferedInputStream(这会添加标记/重置功能)并将其用于 tika 和发送内容。


顺便说一句:你真的应该对资源使用 try来确保所有输入流、流读取器和缓冲读取器都关闭,即使抛出异常也是如此。

于 2018-07-05T19:40:32.820 回答