InputStream无法从JAR读取某些文件

亚历山大·莱特纳(Alexander Leithner):

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

以下文件应正确交付:

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

然而,InputStream只读取文件a/a.txta/b.jsb/e.txt对于所有其他文件,它不返回任何值,并且available() == 0,但是当我不是从JAR而是从提取的Classpath中读取文件时,它就可以工作(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);
}

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

延斯·班曼(Jens Bannmann):

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

这是我的怀疑:tika.detect()显然需要消耗给定流中的字节才能检测到任何东西。方法的javadocs状态,如果它支持标记它只能重置流。因此,你应该验证markSupported()方法InputStream返回的classLoader.getResourceAsStream()实际回报true

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


顺便说一句:您应该真正使用try资源,以确保即使抛出异常也关闭所有输入流,流读取器和缓冲读取器。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章