これまでは、Tomcat をフロントサーバーとして持つ JBoss AS 7.1 を使用していました。現在、Tomcat の代替品として undertow が同梱されている Wildfly (JBoss 8.0) にアップグレードしました。
ファイルのダウンロードでは、ファイルの入力ストリームを読み取り、これを外部コンテキストの応答出力ストリームに書き込みます。これは JBoss AS 7.1 でうまく機能しました - 大きなファイルの場合でも。Undertow では、非常に「小さい」ファイルであっても、次の例外を受け取ります。
13:04:43,292 ERROR [io.undertow.request] (default task-15) Blocking request failed HttpServerExchange{ GET /project/getFile.xhtml}: java.lang.RuntimeException: org.xnio.channels.FixedLengthOverflowException
at io.undertow.servlet.spec.HttpServletResponseImpl.responseDone(HttpServletResponseImpl.java:527)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:287)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:168)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_51]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_51]
at java.lang.Thread.run(Thread.java:744) [rt.jar:1.7.0_51]
Caused by: org.xnio.channels.FixedLengthOverflowException
at io.undertow.conduits.AbstractFixedLengthStreamSinkConduit.write(AbstractFixedLengthStreamSinkConduit.java:97)
at org.xnio.conduits.Conduits.writeFinalBasic(Conduits.java:132) [xnio-api-3.2.0.Final.jar:3.2.0.Final]
at io.undertow.conduits.AbstractFixedLengthStreamSinkConduit.writeFinal(AbstractFixedLengthStreamSinkConduit.java:137)
at org.xnio.conduits.ConduitStreamSinkChannel.writeFinal(ConduitStreamSinkChannel.java:104) [xnio-api-3.2.0.Final.jar:3.2.0.Final]
at io.undertow.channels.DetachableStreamSinkChannel.writeFinal(DetachableStreamSinkChannel.java:172)
at io.undertow.servlet.spec.ServletOutputStreamImpl.writeBufferBlocking(ServletOutputStreamImpl.java:580)
at io.undertow.servlet.spec.ServletOutputStreamImpl.close(ServletOutputStreamImpl.java:614)
at io.undertow.servlet.spec.HttpServletResponseImpl.closeStreamAndWriter(HttpServletResponseImpl.java:451)
at io.undertow.servlet.spec.HttpServletResponseImpl.responseDone(HttpServletResponseImpl.java:525)
... 9 more
はgetFile.xhtml
ダウンロードを呼び出しており、ストリームをコピーするために次のコードが使用されています。
(スペースを節約するために、try、catch、ログ、およびエラー処理を削除しました)
public void downloadFile(FileEntity fileEntity) {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
ec.responseReset();
ec.setResponseContentType(getMimeType(fileEntity.getFile()));
ec.setResponseContentLength(new Long(fileEntity.getFile().length()).intValue());
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + ConversionHelper.validateFilename(fileEntity.getDisplayFileName()) + "\"");
OutputStream output = ec.getResponseOutputStream();
FileInputStream fis = new FileInputStream(fileEntity.getFile());
IOUtils.copy(fis, output);
fc.responseComplete();
}
行を削除することに気付きました
ec.setResponseContentLength(new Long(fileEntity.getFile().length()).intValue());
再び機能させます。ただし、ResponseConentLength は「正しい」です。使用する
ec.setResponseContentLength(new Long(fileEntity.getFile().length()).intValue() + 9);
( に注意+9
)これを解決します。使用+8
-> FixedLengthOverflow
、使用+10
->FixedLengthUnderflow
は+9
ファイルサイズに依存しません。何か案が?私には奇妙に見えます...