Restlet - 使用 StreamingOutput 的 StreamClosedException
Restlet - StreamClosedException using StreamingOutput
我的 Restlet 资源出现问题。它使用 TrueZip 构建 Zip 存档的子集并允许用户下载它。
// Create a Streaming Response Entity.
final StreamingOutput stream = new StreamingOutput() {
@Override
public void write(final OutputStream output) {
ZipBrowser.extract(source, path, output);
}
};
LOGGER.debug("Download of Path {} with the length {} initiated", path, length);
ResponseBuilder rb = Response.ok(stream);
rb.header(HeaderConstants.HEADER_CONTENT_DISPOSITION, CONDISPOVALUE + fileName);
rb.header(HeaderConstants.HEADER_CONTENT_LENGTH, length);
return rb.build();
尽管它有效,但我收到了一个恼人的 StreamClosedException。只有当我尝试下载一个子集而不是整个 Zip 存档时才会出现此错误:
An exception occured writing the responseentity
sun.net.httpserver.StreamClosedException
at sun.net.httpserver.ChunkedOutputStream.flush(ChunkedOutputStream.java:156)
at sun.net.httpserver.PlaceholderOutputStream.flush(ExchangeImpl.java:449)
at org.restlet.engine.adapter.ServerCall.writeResponseBody(ServerCall.java:511)
at org.restlet.engine.adapter.ServerCall.sendResponse(ServerCall.java:454)
at org.restlet.engine.adapter.ServerAdapter.commit(ServerAdapter.java:187)
at org.restlet.engine.adapter.HttpServerHelper.handle(HttpServerHelper.java:144)
at org.restlet.engine.connector.HttpServerHelper.handle(HttpServerHelper.java:64)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)
at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:80)
at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:677)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)
at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:649)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)Unable to send error response
java.io.IOException: headers already sent
at sun.net.httpserver.ExchangeImpl.sendResponseHeaders(ExchangeImpl.java:204)
at sun.net.httpserver.HttpExchangeImpl.sendResponseHeaders(HttpExchangeImpl.java:86)
at org.restlet.engine.connector.HttpExchangeCall.writeResponseHead(HttpExchangeCall.java:148)
at org.restlet.engine.adapter.ServerCall.sendResponse(ServerCall.java:450)
at org.restlet.engine.adapter.ServerAdapter.commit(ServerAdapter.java:205)
at org.restlet.engine.adapter.HttpServerHelper.handle(HttpServerHelper.java:144)
at org.restlet.engine.connector.HttpServerHelper.handle(HttpServerHelper.java:64)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)
at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:80)
at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:677)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)
at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:649)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
这是由于 zip 库和 Restlet Framework 在完成后试图关闭 OutputStream
。
我过去在其他库中遇到过这种情况,并设法通过将我传递给 zip 库的 OutputStream
包装在覆盖 close()
的 class 中来消除异常什么都不做。委托所有其他方法。然后这允许 Restlet 关闭流。
以便在您的代码中调用 Zip 实用程序的行变为:
ZipBrowser.extract(source, path, new WrappedOutputStream(output));
其中 WrappedOutputStream
class 如下所示(需要添加委托方法)。
import java.io.IOException;
import java.io.OutputStream;
public class WrappedOutputStream extends OutputStream {
private final OutputStream delegate;
public WrappedOutputStream(final OutputStream delegate) {
this.delegate = delegate;
}
public void close() throws IOException {
// Do Nothing to allow Restlet to close the underlying stream
}
// TODO Delegate other Outpt Stream methods.
}
我的 Restlet 资源出现问题。它使用 TrueZip 构建 Zip 存档的子集并允许用户下载它。
// Create a Streaming Response Entity.
final StreamingOutput stream = new StreamingOutput() {
@Override
public void write(final OutputStream output) {
ZipBrowser.extract(source, path, output);
}
};
LOGGER.debug("Download of Path {} with the length {} initiated", path, length);
ResponseBuilder rb = Response.ok(stream);
rb.header(HeaderConstants.HEADER_CONTENT_DISPOSITION, CONDISPOVALUE + fileName);
rb.header(HeaderConstants.HEADER_CONTENT_LENGTH, length);
return rb.build();
尽管它有效,但我收到了一个恼人的 StreamClosedException。只有当我尝试下载一个子集而不是整个 Zip 存档时才会出现此错误:
An exception occured writing the responseentity
sun.net.httpserver.StreamClosedException
at sun.net.httpserver.ChunkedOutputStream.flush(ChunkedOutputStream.java:156)
at sun.net.httpserver.PlaceholderOutputStream.flush(ExchangeImpl.java:449)
at org.restlet.engine.adapter.ServerCall.writeResponseBody(ServerCall.java:511)
at org.restlet.engine.adapter.ServerCall.sendResponse(ServerCall.java:454)
at org.restlet.engine.adapter.ServerAdapter.commit(ServerAdapter.java:187)
at org.restlet.engine.adapter.HttpServerHelper.handle(HttpServerHelper.java:144)
at org.restlet.engine.connector.HttpServerHelper.handle(HttpServerHelper.java:64)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)
at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:80)
at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:677)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)
at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:649)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)Unable to send error response
java.io.IOException: headers already sent
at sun.net.httpserver.ExchangeImpl.sendResponseHeaders(ExchangeImpl.java:204)
at sun.net.httpserver.HttpExchangeImpl.sendResponseHeaders(HttpExchangeImpl.java:86)
at org.restlet.engine.connector.HttpExchangeCall.writeResponseHead(HttpExchangeCall.java:148)
at org.restlet.engine.adapter.ServerCall.sendResponse(ServerCall.java:450)
at org.restlet.engine.adapter.ServerAdapter.commit(ServerAdapter.java:205)
at org.restlet.engine.adapter.HttpServerHelper.handle(HttpServerHelper.java:144)
at org.restlet.engine.connector.HttpServerHelper.handle(HttpServerHelper.java:64)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)
at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:80)
at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:677)
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)
at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:649)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
这是由于 zip 库和 Restlet Framework 在完成后试图关闭 OutputStream
。
我过去在其他库中遇到过这种情况,并设法通过将我传递给 zip 库的 OutputStream
包装在覆盖 close()
的 class 中来消除异常什么都不做。委托所有其他方法。然后这允许 Restlet 关闭流。
以便在您的代码中调用 Zip 实用程序的行变为:
ZipBrowser.extract(source, path, new WrappedOutputStream(output));
其中 WrappedOutputStream
class 如下所示(需要添加委托方法)。
import java.io.IOException;
import java.io.OutputStream;
public class WrappedOutputStream extends OutputStream {
private final OutputStream delegate;
public WrappedOutputStream(final OutputStream delegate) {
this.delegate = delegate;
}
public void close() throws IOException {
// Do Nothing to allow Restlet to close the underlying stream
}
// TODO Delegate other Outpt Stream methods.
}