public class VideoStreamingServlet extends HttpServlet{
private static final Logger LOGGER = Logger.getLogger(VideoStreamingServlet.class);
private static final int BUFFER_LENGTH = 1024 * 16;
private static final long EXPIRE_TIME = 1000 * 60 * 60 * 24;
private static final Pattern RANGE_PATTERN = Pattern.compile("bytes=(?<start>\\d*)-(?<end>\\d*)");
private String videoPath;
@Override
public void init() throws ServletException {
videoPath = getInitParameter("videoPath");
}
@Override
protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
private void processRequest(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
String videoFilename = URLDecoder.decode(request.getParameter("video"), "UTF-8");
//String videoFilename = request.getParameter("video");
Path video = Paths.get(videoPath, videoFilename);
LOGGER.info("Absolute File Path "+video.toAbsolutePath());
int length = (int) Files.size(video);
int start = 0;
int end = length - 1;
String range = request.getHeader("Range");
Matcher matcher = RANGE_PATTERN.matcher(range);
if (matcher.matches()) {
String startGroup = matcher.group("start");
start = startGroup.isEmpty() ? start : Integer.valueOf(startGroup);
start = start < 0 ? 0 : start;
String endGroup = matcher.group("end");
end = endGroup.isEmpty() ? end : Integer.valueOf(endGroup);
end = end > length - 1 ? length - 1 : end;
}
int contentLength = end - start + 1;
response.reset();
response.setBufferSize(BUFFER_LENGTH);
response.setHeader("Content-Disposition", String.format("inline;filename=\"%s\"", videoFilename));
response.setHeader("Accept-Ranges", "bytes");
response.setDateHeader("Last-Modified", Files.getLastModifiedTime(video).toMillis());
response.setDateHeader("Expires", System.currentTimeMillis() + EXPIRE_TIME);
response.setContentType(Files.probeContentType(video));
response.setHeader("Content-Range", String.format("bytes %s-%s/%s", start, end, length));
response.setHeader("Content-Length", String.format("%s", contentLength));
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
int bytesRead;
int bytesLeft = contentLength;
ByteBuffer buffer = ByteBuffer.allocate(length);
try (SeekableByteChannel input = Files.newByteChannel(video, READ);
OutputStream output = response.getOutputStream()) {
input.position(start);
while ((bytesRead = input.read(buffer)) != -1 && bytesLeft > 0) {
buffer.clear();
output.write(buffer.array(), 0, bytesLeft < bytesRead ? bytesLeft : bytesRead);
bytesLeft -= bytesRead;
}
}
}
}
This is the controller and the index.html has the view and web.xml has the mapping of the servlet. The problem is whenever i am executing the html it doesnt load the video but after 2 reloads it loads it and plays it fine. the range headers are sent as should be the case and response is also as req. but the video wont load uptill the 3rd reload.
header shot when i load it 1st time it shows the error net::ERR_CONTENT_LENGTH_MISMATCH 206 (Partial Content) and Failed instead of 206 despite the 206 being shown in the picture.
header shot when i load it for 2nd time shows the same error as above.
from the 3 rd time it somehow gets the data and shows 206 along with the same in header. but when i play the video it continuously fails with the above error but the video somehow plays. of the 350 reqs only 5-6 actually succeed. rest all fail. after realoading it 3rd time in the above ss u can see that of 11, 7 have failed while only 3 have succeded. but when i use the same code in localhost everything is fine and video plays as expected without any error. Can someone please tell me if the code has any fault or its an issue with the nginx server. As i have said that it works fine when i try it in eclipse with my tomcat 8.5 and use it on localhost. please help. i have been trying to solve this for the past 7 days. anyhelp will be appreciated and thanks in advance.