Java-Servlet: Streaming of a Quicktime-video causes a ClientAbortException
I am trying to program a small webproxy based on a java-servlet. This proxy has only one task:
- HTML shall be passed to the client which sent the request (GET requests with destination port 80 are rerouted to the proxy by firewall rules).
- An embedded quicktime-video shall be replaced by another quicktime-video and shall be passed to the client instead of the initially requested (here, too, the initially sent GET request of the client is rerouted to the proxy first. The proxy detects that the requested content type is not HTML and concludes from this issue that the content must be a quicktime-video in this special case (see HTML below)). As a result the proxy shall send/stream a particular video to the client.
This should happen for the following HTML document that is going to be requested by the client:
<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>
The source code of the proxy-servlet is as follows:
protected void doGet开发者_Go百科(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();
}
}
The HTML document is delivered by the proxy and rendered by the browser correctly. But the GET request for the quicktime-video respectively the response of the proxy causes a ClientAbortException: java.net.SocketException: Broken pipe at line 34 of the servlet-sourcecode.
I tried various kinds of OutputStreams (BufferedOutputStream, DataOutputStream, PipedOutputStream, ServletOutputStream). None of them did work...
Does anybody see my mistake?
Yours faithfully, Ashiaka
Lot of players for streaming media expects the server side to support Range
requests. Usually the servletcontainer's (Tomcat, JBoss AS, Glassfish, etc) own default servlet supports this already. So if there's a way to publish the movie folder into the web by just adding the folder to the server configuration, so that you don't need a homegrown servlet for this, then I'd go on this route.
For example, in Tomcat you could achieve this by just moving the file into Tomcat/webapps/movies
folder, or by adding the following line to its /conf/server.xml
:
<Context docBase="/var/www/movies" path="/movies" />
If you put the final_lion.mov
file in Tomcat/webapps/movies
or /var/www/movies
folder depending on the configuration choice, then you should be able to access it by http://localhost:8080/movies/final_lion.mov without the need for any homegrown servlet. Instead, Tomcat's own DefaultServlet
will be used to stream the static content.
But if there's no way, then you need to rewrite your servlet code in such way that it supports Range
requests (also known as download resumes). You can find a concrete kickoff example in this article.
I have same issue faced and spend few days and try to dig one by one. This is related to your browser cache issue. You may try to use this code. It works for me.
response.addHeader("Cache-Control", "no-transform, max-age=0");
精彩评论