这是我第一次觉得我需要问一个问题,因为我似乎无法在任何地方找到答案。
因此,在这个应用程序中,我为我的摄影师朋友制作了一个使用 html5 视频作为背景的简单网站页面。为了让我的朋友在未来进行更改,我想使用 appengine blobstore 为后台上传的视频提供服务。一切似乎都很好,除了在 Safari 中,视频从未收到或收到错误。
这是我提供服务的 servlet 类:
public class Serve extends HttpServlet {
private static final long serialVersionUID = 1L;
private BlobstoreService blobstore = BlobstoreServiceFactory.getBlobstoreService();
private DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String format = req.getParameter("video");
Key key = KeyFactory.createKey("Video", "None");
if(format.equals("mp4")){
key = KeyFactory.createKey("Video", "MP4");
resp.setHeader("Content-type", "video/mp4");
}
if(format.equals("webm")){
key = KeyFactory.createKey("Video", "WebM");
resp.setHeader("Content-type", "video/webm");
}
try{
Entity e = datastore.get(key);
String blobKey = (String)e.getProperty("Blob-Key");
BlobKey bKey = new BlobKey(blobKey);
resp.setHeader("Cache-Control", "max-age=31557600, must-revalidate");
//resp.setHeader("Transfer-Encoding", "chunked");
blobstore.serve(bKey, resp);
}
catch (EntityNotFoundException error){
resp.getWriter().print("No video found");
}
}
}
编辑:删除了 Transfer-Encoding 标头。
现在在开发服务器上,当我尝试仅在 Safari 中访问 /serve?video=mp4 时出现此异常:
[java] WARNING: IOException thrown while closing Closeable.
[java] org.mortbay.jetty.EofException
[java] at org.mortbay.jetty.HttpGenerator.flush(HttpGenerator.java:787)
[java] at org.mortbay.jetty.HttpConnection.flushResponse(HttpConnection.java:693)
[java] at org.mortbay.jetty.HttpConnection$Output.close(HttpConnection.java:992)
[java] at com.google.appengine.repackaged.com.google.common.io.Closeables.close(Closeables.java:77)
[java] at com.google.appengine.api.blobstore.dev.ServeBlobFilter.serveBlob(ServeBlobFilter.java:195)
[java] at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:67)
[java] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
[java] at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
[java] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
[java] at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125)
[java] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
[java] at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:368)
[java] at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:351)
[java] at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116)
[java] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
[java] at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
[java] at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
[java] at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
[java] at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
[java] at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
[java] at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:97)
[java] at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
[java] at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:485)
[java] at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
[java] at org.mortbay.jetty.Server.handle(Server.java:326)
[java] at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
[java] at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
[java] at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:547)
[java] at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
[java] at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
[java] at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
[java] at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
[java] Caused by: java.io.IOException: Broken pipe
[java] at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
[java] at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
[java] at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:89)
[java] at sun.nio.ch.IOUtil.write(IOUtil.java:46)
[java] at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:450)
[java] at org.mortbay.io.nio.ChannelEndPoint.flush(ChannelEndPoint.java:169)
[java] at org.mortbay.io.nio.SelectChannelEndPoint.flush(SelectChannelEndPoint.java:221)
[java] at org.mortbay.jetty.HttpGenerator.flush(HttpGenerator.java:721)
[java] ... 31 more
[java]
[java] Sep 20, 2013 2:48:25 PM com.google.appengine.repackaged.com.google.common.io.Closeables close
[java] WARNING: IOException thrown while closing Closeable.
[java] org.mortbay.jetty.EofException
[java] at org.mortbay.jetty.HttpGenerator.flush(HttpGenerator.java:787)
[java] at org.mortbay.jetty.HttpConnection.flushResponse(HttpConnection.java:693)
[java] at org.mortbay.jetty.HttpConnection$Output.close(HttpConnection.java:992)
[java] at com.google.appengine.repackaged.com.google.common.io.Closeables.close(Closeables.java:77)
[java] at com.google.appengine.api.blobstore.dev.ServeBlobFilter.serveBlob(ServeBlobFilter.java:195)
[java] at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:67)
[java] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
[java] at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
[java] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
[java] at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125)
[java] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
[java] at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:368)
[java] at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:351)
[java] at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116)
[java] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
[java] at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
[java] at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
[java] at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
[java] at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
[java] at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
[java] at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:97)
[java] at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
[java] at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:485)
[java] at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
[java] at org.mortbay.jetty.Server.handle(Server.java:326)
[java] at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
[java] at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
[java] at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:547)
[java] at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
[java] at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
[java] at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
[java] at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
[java] Caused by: java.io.IOException: Broken pipe
[java] at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
[java] at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
[java] at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:89)
[java] at sun.nio.ch.IOUtil.write(IOUtil.java:46)
[java] at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:450)
[java] at org.mortbay.io.nio.ChannelEndPoint.flush(ChannelEndPoint.java:169)
[java] at org.mortbay.io.nio.SelectChannelEndPoint.flush(SelectChannelEndPoint.java:221)
[java] at org.mortbay.jetty.HttpGenerator.flush(HttpGenerator.java:721)
[java] ... 31 more
该视频仍将显示在此页面上,但是在生产中没有任何反应。此外,我在 appengine 控制台中没有收到任何日志,所以如果有其他错误,我不会。我知道该视频已正确上传,因为它可以在谷歌浏览器中使用。Google Chrome 将发回响应标头并播放视频。我也尝试过使用 curl,它也将所有内容都发回。是否有我遗漏的东西或者我需要拿出一些东西才能让它在 Safari 中正常工作。
编辑:我还想知道在 Safari 中是否像在 Firefox、Chrome 和 Opera 中一样接收到 blobstore 请求的响应标头?
感谢您提供的任何建议。