Java-сервлет: потоковое видео Quicktime вызывает исключение ClientAbortException - PullRequest
1 голос
/ 26 августа 2011

Я пытаюсь запрограммировать небольшой веб-прокси на основе Java-сервлета.Этот прокси имеет только одну задачу:

  1. HTML должен быть передан клиенту, который отправил запрос (запросы GET с портом назначения 80 перенаправляются на прокси по правилам брандмауэра).
  2. Встроенное quicktime-video должно быть заменено другим quicktime-video и должно быть передано клиенту вместо первоначально запрошенного (здесь также первоначально отправленный GET-запрос клиента перенаправляется на прокси-сервер первым. Прокси-сервер обнаруживает, чтоЗапрашиваемый тип контента не является HTML, и из этого вопроса делается вывод, что в этом особом случае контент должен быть quicktime-видео (см. 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 для quicktime-video соответственно ответа прокси-сервера вызывает ClientAbortException: java.net.SocketException: Broken pipe в строке 34 сервлет-исходного кода.

Я пробовал различные виды OutputStreams (BufferedOutputStream, DataOutputStream, PipedOutputStream, ServletOutputStream).Никто из них не сработал ...

Кто-нибудь видит мою ошибку?

С уважением, Ашиака

Ответы [ 2 ]

2 голосов
/ 26 августа 2011

Многие проигрыватели потокового мультимедиа ожидают, что на стороне сервера будут поддерживаться Range запросы.Обычно собственный сервлет по умолчанию для сервлет-контейнера (Tomcat, JBoss AS, Glassfish и т. Д.) Уже поддерживает это.Поэтому, если есть способ опубликовать папку фильма в Интернете, просто добавив ее в конфигурацию сервера, чтобы вам не понадобился доморощенный сервлет, тогда я бы пошел по этому пути.

Например, в 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 без необходимости использования какого-либо доморощенного сервлета.Вместо этого будет использоваться собственный DefaultServlet от Tomcat для потоковой передачи статического содержимого.

Но если нет никакого способа, вам нужно переписать код сервлета таким образом, чтобы он поддерживал Range запросы (также известные как возобновление загрузки).Вы можете найти конкретный пример запуска в этой статье .

0 голосов
/ 17 января 2013

Я столкнулся с той же проблемой, провожу несколько дней и пытаюсь покопаться один за другим.Это связано с проблемой кеша вашего браузера.Вы можете попробовать использовать этот код.Это работает для меня.

response.addHeader ("Cache-Control", "без преобразования, max-age = 0");

...