【问题标题】:Restlet - StreamClosedException using StreamingOutputRestlet - 使用 StreamingOutput 的 StreamClosedException
【发布时间】:2016-02-12 09:47:23
【问题描述】:

我的 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$1.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$1.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)

【问题讨论】:

    标签: java exception restlet truezip


    【解决方案1】:

    这是由 zip 库和 Restlet 框架在完成后尝试关闭 OutputStream 引起的。

    我过去曾在其他库中遇到过这种情况,并设法通过将 OutputStream 包装在一个覆盖 close() 的类中来消除异常。委托所有其他方法。然后这允许 Restlet 关闭流。

    因此在您的代码中调用 Zip 实用程序的行变为:

     ZipBrowser.extract(source, path, new WrappedOutputStream(output));
    

    WrappedOutputStream 类如下所示(需要添加委托方法)。

    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.
    }
    

    【讨论】:

    • 好主意!刚试了一下就可以了。非常感谢:-)
    猜你喜欢
    • 2017-04-27
    • 2015-01-28
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 2018-12-21
    • 1970-01-01
    相关资源
    最近更新 更多