Java-Servlet:Quicktime-video的流式传输导致ClientAbortException

时间:2011-08-26 14:14:43

标签: java servlets stream quicktime

我正在尝试基于java-servlet编写一个小型webproxy。这个代理有 只有一项任务:

  1. HTML应传递给发送请求的客户端(目的端口80的GET请求通过防火墙规则重新路由到代理)。
  2. 嵌入式quicktime-video应由另一个quicktime-video替换,并应传递给客户端而不是最初请求的(此处,客户端最初发送的GET请求也会先重新路由到代理。检测到所请求的内容类型不是HTML,并从此问题得出结论,在这种特殊情况下内容必须是quicktime-video(请参阅下面的HTML))。因此,代理应将特定视频发送/流式传输到客户端。
  3. 对于客户端要求的以下HTML文档,应该会发生这种情况:

    <html>
    <head>
    
    <h1> Heading!</h1>
    </head>
    <body>
    
    <h1>My First Heading</h1>
    
    <object width="160" height="144"
    classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
    codebase="http://www.apple.com/qtactivex/qtplugin.cab">
    <param name="src" value="final_lion.mov">
    <param name="autoplay" value="true">
    <param name="controller" value="false">
    
    <embed src="final_lion.mov" width="480" height="432"
    autoplay="true" controller="false"
    pluginspage="http://www.apple.com/quicktime/download/">
    </embed>
    
    </object> 
    
    </body>
    </html> 
    

    proxy-servlet的源代码如下:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
        ServletContext context = getServletContext();
        PrintWriter out = null;
        try {
                String result = new String();
                String urlStr = request.getRequestURL().toString();
    
    
                URL url = new URL(urlStr);
                URLConnection conn = url.openConnection();
    
                response.setContentType(conn.getContentType());
    
                if (conn.getContentType().contains("text/"))
                {
                    out = response.getWriter(); 
                    out.write(getTextContent(conn));
                    out.flush();
                    out.close();
                }
                else
                {
                    File file = new File("/var/www/final_lion.mov");
                    response.setContentType("video/quicktime");
                    response.setHeader("Content-Length", Long.toString(file.length()));
                    response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
                    FileInputStream input = new FileInputStream(file);
                    OutputStream output = response.getOutputStream();
    
                    byte[] buffer = new byte[4096];
                    int read = 0;
                    while((read = input.read(buffer)) != -1 ){
                        output.write(buffer,0,read);
                    }
                    input.close();
                    output.flush();
                    output.close();
    
                }
            } catch (Exception e) {
                    context.log("error", e);
            }
    }
    
    private String getTextContent(URLConnection conn)
    {
        try{
            BufferedReader rd = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            StringBuffer sb = new StringBuffer();
            String line;
            while ((line = rd.readLine()) != null) {
                sb.append(line + "\n");
            }
            rd.close();
            return sb.toString();
        }catch (Exception e){
            return "error: " + e.toString();
        }
    }
    

    HTML文档由代理提供,并由浏览器正确呈现。但是对于quicktime-video的GET请求和代理的响应分别导致了servlet-sourcecode第34行的 ClientAbortException:java.net.SocketException:Broken pipe

    我尝试了各种OutputStreams(BufferedOutputStream,DataOutputStream,PipedOutputStream,ServletOutputStream)。他们都没有工作......

    有人看到我的错误吗?

    你的忠实, Ashiaka

2 个答案:

答案 0 :(得分:2)

许多流媒体播放器都希望服务器端支持Range个请求。通常servletcontainer(Tomcat,JBoss AS,Glassfish等)拥有默认的servlet已经支持了这一点。因此,如果有一种方法可以通过将文件夹添加到服务器配置来将电影文件夹发布到Web中,这样您就不需要本地的servlet了,那么我将继续这条路线。

例如,在Tomcat中,只需将文件移动到Tomcat/webapps/movies文件夹中,或将以下行添加到/conf/server.xml中即可实现此目的:

<Context docBase="/var/www/movies" path="/movies" />

如果您将final_lion.mov文件放在Tomcat/webapps/movies/var/www/movies文件夹中,具体取决于配置选项,那么您应该可以http://localhost:8080/movies/final_lion.mov访问该文件,而无需任何自产的servlet。相反,Tomcat自己的DefaultServlet将用于流式传输静态内容。

但如果没办法,那么你需要以支持Range请求(也称为下载简历)的方式重写servlet代码。您可以在this article中找到具体的启动示例。

答案 1 :(得分:0)

我面临同样的问题,花了几天时间,逐一尝试挖掘。 这与您的浏览器缓存问题有关。您可以尝试使用此代码。它对我有用。

response.addHeader(“Cache-Control”,“no-transform,max-age = 0”);