I'm currently trying to load a video from a database and stream it via JSP to a browser. Everything is working fine on most browsers except when using Safari, which only shows an empty player that doesn't show any video.
The problem is in the outputStream socket,
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
Safari restarts the video stream a couple of times and i get a socket exception.
org.apache.catalina.connector.ClientAbortException: java.net.SocketException: Connection reset by peer: socket write error
Safari keeps requesting a specific byte-range in the http-header:
"bytes=0-1"
code:
<%@ page import="java.io.*"%>
<%@ page import="java.net.*"%>
<%@ page import="com.mysql.jdbc.*"%>
<%@ page import="java.sql.*"%>
<%@page language="java" trimDirectiveWhitespaces="true"%>
<%@include file="settings.jsp"%>
<%
session = request.getSession(false);
if (session != null) {
int userId = 0;
try {
userId = (new Integer(session.getAttribute("user_id").toString())).intValue();
}
catch (Exception ex) {
// nothing
}
int videoId = 0;
try {
if (request.getParameter("video_id") != null) {
videoId = (new Integer(request.getParameter("video_id"))).intValue();
}
}
catch (Exception ex) {
// nothing
}
int videoType = 0;
try {
if (request.getParameter("video_type") != null) {
videoType = (new Integer(request.getParameter("video_type"))).intValue();
}
}
catch (Exception ex) {
// nothing
}
if (userId > 0 && videoId > 0 && videoType > 0) {
java.sql.Connection connection = null;
java.sql.PreparedStatement queryStatement = null;
StringBuffer sql = null;
try {
String connectionURL = "jdbc:mysql://" + DB_HOST_NAME + ":" + DB_PORT + "/" + DB_NAME;
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(connectionURL, DB_USER_NAME, DB_USER_PASSWORD);
if (!connection.isClosed()) {
sql = new StringBuffer();
sql.append("SELECT ");
sql.append("video.id AS id, ");
sql.append("video.title AS title, ");
sql.append("video.video_url_hd AS video_url_hd, ");
sql.append("video.video_url_sd AS video_url_sd, ");
sql.append("video.video_img_url AS video_img_url, ");
sql.append("video.description AS description ");
sql.append("FROM " + DB_NAME + ".video ");
sql.append("INNER JOIN " + DB_NAME + ".video_visibility ON video_visibility.video_id = video.id ");
sql.append("INNER JOIN " + DB_NAME + ".users ON users.id = ? ");
sql.append("WHERE video_visibility.right_gr_id IN (users.right_gr_id, 0) AND video.id = ? ");
sql.append("ORDER BY video.sequence ");
queryStatement = connection.prepareStatement(sql.toString());
queryStatement.setInt(1, userId);
queryStatement.setInt(2, videoId);
ResultSet rs = queryStatement.executeQuery();
if (rs != null) {
if (rs.next()) {
String title = rs.getString("title");
String imgURL = rs.getString("video_img_url");
String videoSDURL = rs.getString("video_url_sd");
String videoHDURL = rs.getString("video_url_hd");
rs.close();
/*
* Add logging
*/
String logSql = "INSERT INTO " + DB_LOG_NAME + ".webclient_log (client_type, user_id, video_id, message, client_ip) " + "VALUES('"
+ CLIENT_TYPE + "', '" + userId + "', '" + videoId + "', 'Show Video:" + title + " / videoType=" + videoType + "', '"
+ request.getRemoteAddr() + "' )";
queryStatement.close();
queryStatement = connection.prepareStatement(logSql);
queryStatement.executeUpdate();
/*
* Stream File
*/
String filePath = null;
if (videoType == 1) {
String path = "/video/" + videoSDURL;
filePath = getServletContext().getRealPath(path);
}
else if (videoType == 2) {
String path = "/video/" + videoHDURL;
filePath = getServletContext().getRealPath(path);
}
File downloadFile = new File(filePath);
FileInputStream inStream = new FileInputStream(downloadFile);
// if you want to use a relative path to context root:
String relativePath = getServletContext().getRealPath("");
// obtains ServletContext
ServletContext context = getServletContext();
// gets MIME type of the file
String mimeType = context.getMimeType(filePath);
if (mimeType == null) {
// set to binary type if MIME mapping not found
mimeType = "application/octet-stream";
}
// modifies response
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
//we support skipping
response.setHeader("Accept-Ranges", "bytes");
// obtains response's output stream
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
outStream.flush();
inStream.close();
outStream.close();
}
}
}
}
catch (Exception ex) {
System.out.println(ex.toString());
}
finally {
if (queryStatement != null)
queryStatement.close();
if (connection != null)
connection.close();
sql = null;
}
}
}
%>