我在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写入浏览器以播放视频?
答案 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浏览器中使用。