【问题标题】:Java-Servlet: Streaming of a Quicktime-video causes a ClientAbortExceptionJava-Servlet:Quicktime 视频的流式传输会导致 ClientAbortException
【发布时间】:2011-11-04 13:56:38
【问题描述】:

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

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

这应该发生在客户端将要请求的以下 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 请求和代理的响应会导致 ClientAbortException: java.net.SocketException: Broken pipe 在 servlet-sourcecode 的第 34 行。

我尝试了各种输出流(BufferedOutputStream、DataOutputStream、PipedOutputStream、ServletOutputStream)。他们都没有工作......

有人看到我的错误吗?

您忠实的, 芦香

【问题讨论】:

  • 客户端可能由于某种原因停止下载内容。 /var/www/final_lion.mov 有多大?可以用小电影试试吗?
  • final_lion.mov 大小为 1 MB。我还尝试了一个较小的视频。同样的问题。

标签: java servlets stream quicktime


【解决方案1】:

许多流媒体播放器希望服务器端支持Range 请求。通常 servlet 容器(Tomcat、JBoss AS、Glassfish 等)自己的默认 servlet 已经支持这一点。因此,如果有一种方法可以将电影文件夹发布到网络上,只需将文件夹添加到服务器配置中,这样您就不需要为此使用自制的 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 将用于流式传输静态内容。

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2011-10-27
      • 2011-07-31
      • 1970-01-01
      • 2011-12-23
      • 2010-11-03
      • 1970-01-01
      • 1970-01-01
      • 2012-11-06
      • 1970-01-01
      相关资源
      最近更新 更多