2016-02-12 3 views
3

У меня возникают проблемы с моим ресурсом Restlet. Он использует TrueZip для создания подмножества Zip-архива и позволяет пользователю его загружать.Restlet - StreamClosedException с использованием StreamingOutput

// 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) 

ответ

2

Это вызвано как библиотеки почтового индекса и Restlet Framework пытается закрыть OutputStream, когда они закончили.

Я уже сталкивался с этим в прошлом с другими библиотеками и сумел исключить исключение, обернув OutputStream. Я перехожу к библиотеке zip в класс, который переопределяет 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. 
} 
+1

Отличная идея! Просто попробовал и работает. Большое спасибо :-) – user1291536