I'm making a simple Java com.sun.net.httpserver.HttpServer
to serve static video files. If I return status code 206, Partial Content, when I try access it through the browser the video is not able to play (the video plays fine with status code 200 but I wanted to be able to seek and loop the video), this is my HttpHandler
:
final String path = StaticHandler.toPathSafe(httpExchange.getRequestURI().getPath());
System.out.println(path);
final File file = new File(path);
if (file.isFile())
{
int code = 200;
long position = 0L;
long end = file.length();
if (httpExchange.getRequestHeaders().containsKey("Range"))
{
try
{
long[] range = StaticHandler.parseRange(httpExchange.getRequestHeaders().get("Range").get(0));
position = range[0];
if (range[1] != -1)
end = range[1];
// the video loads fine when code = 200;
code = 206;
httpExchange.getResponseHeaders().set("Content-Range", "bytes " + position + "-" + end + "/" + file.length());
}
catch (Exception e)
{
e.printStackTrace();
}
}
httpExchange.getResponseHeaders().set("Accept-Range", "bytes");
httpExchange.getResponseHeaders().set("Content-Type", "video/mp4");
httpExchange.getResponseHeaders().set("Content-Length", String.valueOf(end - position));
System.out.println("Response: " + position + ", " + end);
httpExchange.sendResponseHeaders(code, 0L);
final FileChannel fileChannel = new FileInputStream(file).getChannel();
final WritableByteChannel responseChannel = Channels.newChannel(response.getOutputStream());
fileChannel.transferTo(position, end - position, responseChannel);
responseChannel.close();
fileChannel.close();
}
else
{
System.out.println("404");
httpExchange.sendResponseHeaders(404, -1);
}
The above code fails to load on chrome but works fine in firefox, here are the headers I get in Chrome:
Response Headers:
Accept-range: bytes
Content-length: 31491166
Content-range: bytes 0-31491166/31491166
Content-type: video/mp4
Date: Sat, 27 Jul 2019 14:32:55 GMT
Transfer-encoding: chunked
Request Headers:
Accept: */*
Accept-Encoding: identity;q=1, *;q=0
Accept-Language: en-US,en;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Host: 192.168.56.1:5000
Pragma: no-cache
Range: bytes=0-
Referer: http://192.168.56.1:5000/30MB.mp4
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Am I missing something and/or is there something wrong in my code?
Range is inclusive start-end. Not start-length
For example:
Content-range: bytes 0-0/31491166
Returns 1 byte (from byte zero to byte zero)
Your code doesn’t work because the browser is waiting for one more byte that is never sent.
Use below code snippet. it's working and tested on all browsers Safari, Firefox, and Chrome.
protected byte[] prepareContent(final HttpHeaders headers, byte[] media,
String range) throws IOException {
long rangeStart = 0;
long rangeEnd;
long fileSize = media.length;
String[] ranges = range.split("-");
rangeStart = Long.parseLong(ranges[0].substring(6));
if (ranges.length > 1) {
rangeEnd = Long.parseLong(ranges[1]);
} else {
rangeEnd = fileSize - 1;
}
if (fileSize < rangeEnd) {
rangeEnd = fileSize - 1;
}
String contentLength = String.valueOf((rangeEnd - rangeStart) + 1);
headers.add("Content-Length", contentLength);
headers.add("Content-Range", "bytes " + rangeStart + "-" + rangeEnd + "/" + fileSize);
headers.add("Content-Type", "video/mp4");
headers.add("Accept-Ranges","bytes");
return readByteRange(media, rangeStart, rangeEnd);
}
private byte[] readByteRange(byte[] media, long start, long end) throws IOException {
try (InputStream inputStream = new ByteArrayInputStream(media);
ByteArrayOutputStream bufferedOutputStream = new ByteArrayOutputStream()) {
int nRead;
while ((nRead = inputStream.read(media, 0, media.length)) != -1) {
bufferedOutputStream.write(media, 0, nRead);
}
bufferedOutputStream.flush();
byte[] result = new byte[(int) (end - start) + 1];
System.arraycopy(bufferedOutputStream.toByteArray(), (int) start, result, 0, result.length);
return result;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With