在Chrome中,将Wrtie ByteArrayOutputStream转换为Html5视频失败(Java Servlet)

时间:2018-11-07 04:19:00

标签: java google-chrome servlets html5-video bytearrayoutputstream

我在jsp中有一个视频标签,src是servlet的网址。

<video src="/MyApp/video" controls="true"></video>

这是对应的servlet

public class VideoServlet extends HttpServlet {

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        go(req, resp);
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    private void go(HttpServletRequest request, HttpServletResponse response) throws IOException {
        File file = new File("/Users/me/video.mp4");
        int fileSize = (int) file.length();
        FileInputStream inputStream = null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(4096);
        try {
            inputStream = new FileInputStream(file);
            final byte[] buf = new byte[1024 * 8];
            for (int v; (v = inputStream.read(buf)) >= 0;) {
                if (v > 0)
                    outputStream.write(buf, 0, v);
            }

            response.setHeader("Accept-Ranges", "bytes");
            response.setContentType("video/mp4");
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            response.setContentLength(fileSize);
            response.setHeader("Content-Range", "bytes " + 0 + "-" + fileSize + "/" + fileSize);

            outputStream.writeTo(response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            inputStream.close();
            outputStream.close();
        }
    }
}

当我使用Firefox时,它可以工作,可以在页面加载后播放视频,但是在Chrome浏览器中,我收到了EofException(jetty)或ClientAbortException(tomcat)。

这是使用码头时的异常堆栈跟踪:

org.eclipse.jetty.io.EofException
    at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:292)
    at org.eclipse.jetty.io.WriteFlusher.flush(WriteFlusher.java:429)
    at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:322)
    at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:372)
    at org.eclipse.jetty.server.HttpConnection$SendCallback.process(HttpConnection.java:756)
    at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:241)
    at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:224)
    at org.eclipse.jetty.server.HttpConnection.send(HttpConnection.java:522)
    at org.eclipse.jetty.server.HttpChannel.sendResponse(HttpChannel.java:735)
    at org.eclipse.jetty.server.HttpChannel.write(HttpChannel.java:786)
    at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:234)
    at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:218)
    at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:530)
    at java.io.ByteArrayOutputStream.writeTo(ByteArrayOutputStream.java:167)
    at VideoServlet.go(VideoServlet.java:56)
    at VideoServlet.doGet(VideoServlet.java:25)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:833)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1650)
    at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:206)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:219)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at org.eclipse.jetty.server.Server.handle(Server.java:561)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:334)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:104)
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:679)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:597)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: Broken pipe
    at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
    at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
    at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
    at sun.nio.ch.IOUtil.write(IOUtil.java:65)
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
    at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:270)
    ... 49 more

我的用法是否错误或者是浏览器问题?

如果我的用法有误,应该如何将ByteArrayOutputStream写入浏览器以播放视频?

1 个答案:

答案 0 :(得分:0)

我看到了文档https://tools.ietf.org/html/rfc7233#section-4.2

如果Content-Range字段值包含一个byte-range-resp,则其last-byte-pos值小于其first-byte-pos值,或者full-length值小于或等于其最后一个字节的pos值。

所以我改变了

response.setHeader("Content-Range", "bytes " + 0 + "-" + fileSize + "/" + fileSize);

response.setHeader("Content-Range", "bytes " + 0 + "-" + (fileSize - 1) + "/" + fileSize);

它现在可以在Chrome浏览器中使用。