我已经为我的Javalin应用程序构建了一个JAR文件,并且代码运行正常。但是,从inputStream.available() == 0
的JAR文件中读取某些资源文件失败,但是对于其他一些文件也是如此。
以下文件应正确交付:
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而是从提取的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);
}
我在这里错过什么还是做错了吗?
答案 0 :(得分:1)
我怀疑可能是MIME类型检测。首先,尝试将其遗漏,看看是否可以解决您的问题。
这是我的怀疑:tika.detect()
显然需要消耗给定流中的字节才能检测到任何东西。 method javadocs状态表明,只有支持标记,它才能重置流。因此,您应该验证InputStream
返回的classLoader.getResourceAsStream()
中的markSupported()
method实际返回了true
。
如果没有,例如Tika消耗文件的所有内容,直到可以确定文件的类型,然后无法重置流,然后再没有其他内容可以发送给客户端了。在这种情况下,您应该将原始InputStream
包装在BufferedInputStream
中(这会添加标记/重置功能),并将其用于tika和发送内容。
顺便说一句:您应该真正使用try with resources来确保即使抛出异常也关闭所有输入流,流读取器和缓冲读取器。