我目前正在尝试从数据库加载视频并通过JSP将其流式传输到浏览器。在大多数浏览器上一切正常,除非使用Safari,它只显示一个没有显示任何视频的空播放器。
问题在于outputStream套接字,
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
Safari重启视频流几次,我收到套接字异常。
org.apache.catalina.connector.ClientAbortException: java.net.SocketException: Connection reset by peer: socket write error
Safari不断在http-header中请求特定的字节范围:
"bytes=0-1"
代码:
<%@ 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;
}
}
}
%>