2011-08-26 4 views
1

java-servlet을 기반으로 작은 webproxy를 프로그래밍하려고합니다.Java-Servlet : Quicktime-video 스트리밍으로 인해 ClientAbortException이 발생합니다.

  1. HTML은 (대상 포트 (80)와 GET 요청을 방화벽 규칙에 의해 프록시로 다시 라우팅) 요청을 보낸 클라이언트에 전달되어야한다이 프록시는 하나의 작업이 있습니다.
  2. 임베디드 퀵타임 비디오는 다른 퀵타임 비디오로 대체되어야하며, 처음에 요청한 것 대신에 클라이언트로 전달되어야한다. (여기에서도 클라이언트의 처음 보낸 GET 요청은 먼저 프록시로 재 라우팅된다.) 프록시 요청한 콘텐츠 유형이 HTML이 아니라는 것을 감지하고이 특수한 경우에 콘텐츠가 퀵타임 동영상이어야한다는 점에서이 문제로 결론지었습니다 (아래 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> 

프록시 - 서블릿의 소스 코드를 그대로 :

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 문서는 프록시에 의해 전달되고 브라우저에서 올바르게 렌더링됩니다. 그러나 GET 요청에 대한 프록시의 응답은 각각 ClientAbortException이 발생합니다. java.net.SocketException : 브로커 파이프 servlet-sourcecode 34 행.

다양한 종류의 OutputStream (BufferedOutputStream, DataOutputStream, PipedOutputStream, ServletOutputStream)을 시도했습니다. 그들 중 누구도 일을하지 못했습니다 ...

아무도 내 실수를 볼 수 있습니까? 미디어 스트리밍 플레이어의

너의 충실, Ashiaka

+0

클라이언트가 어떤 이유로 다운로드를 중지 할 수 있습니다. /var/www/final_lion.mov의 크기는 얼마입니까? 작은 영화로해볼 수 있습니까? –

+0

final_lion.mov의 크기는 1MB입니다. 나는 또한 작은 비디오로 시도했다. 그것에 관한 동일한 문제. 이 답변에 대해서는 – ashiaka

답변

2

부지는 서버 측 Range 요청을 지원 할 예정이다. 보통 servletcontainer (Tomcat, JBoss AS, Glassfish 등)의 자체 서블릿은 이미 이것을 지원합니다. 따라서 폴더를 서버 구성에 추가하여 영화 폴더를 웹에 게시하는 방법이 있으면이 경우 자체 제작 서블릿이 필요하지 않으므로이 경로로 이동하십시오.

예를 들어, 톰캣에 당신은, 또는 /conf/server.xml에 다음 줄을 추가하여 단지 Tomcat/webapps/movies 폴더로 파일을 이동하여이를 수 :

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

당신이 Tomcat/webapps/movies 또는 /var/www/movies 폴더에 final_lion.mov 파일을 넣으면 구성 선택 사항에 따라 자체 개발 서블릿이 필요없이 http://localhost:8080/movies/final_lion.mov까지 액세스 할 수 있어야합니다. 대신 Tomcat의 자체 DefaultServlet이 정적 컨텐츠를 스트리밍하는 데 사용됩니다.

그러나 방법이 없다면 Range 요청 (다운로드 재개라고도 함)을 지원하는 방식으로 서블릿 코드를 다시 작성해야합니다. 콘크리트 킥오프 예제는 this article에서 찾을 수 있습니다.

+0

xx입니다. 나는 오늘 오후에 그것을 시도 할 것이다. – ashiaka

+0

멋진 기사! 그것은 일하고있어 :) – ashiaka

+0

당신을 진심으로 환영합니다. – BalusC

0

나는 똑같은 문제에 직면 해 있으며 며칠을 보내고 하나씩 파헤려고 노력합니다. 이것은 브라우저 캐시 문제와 관련이 있습니다. 이 코드를 사용해보십시오.그것은 나를 위해 작동합니다.

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

관련 문제