Chrome 如果传输状态为 206 部分内容,则无法加载视频
Chrome fails to load video if transferred with status 206 Partial Content
我正在制作一个简单的 Java com.sun.net.httpserver.HttpServer
来提供静态视频文件。如果我 return 状态代码 206,部分内容,当我尝试通过浏览器访问它时,视频无法播放(视频播放状态代码 200 正常,但我希望能够搜索和循环播放视频), 这是我的 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);
}
以上代码无法在 chrome 上加载,但在 firefox 中运行良好,这是我在 Chrome 中获得的 headers:
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
我是不是遗漏了什么and/or我的代码有问题吗?
范围包括开始到结束。不是起始长度
例如:
Content-range: bytes 0-0/31491166
Returns 1 字节(从字节零到字节零)
您的代码不起作用,因为浏览器正在等待一个从未发送过的字节。
使用下面的代码片段。它在所有浏览器 Safari、Firefox 和 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;
}
}
我正在制作一个简单的 Java com.sun.net.httpserver.HttpServer
来提供静态视频文件。如果我 return 状态代码 206,部分内容,当我尝试通过浏览器访问它时,视频无法播放(视频播放状态代码 200 正常,但我希望能够搜索和循环播放视频), 这是我的 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);
}
以上代码无法在 chrome 上加载,但在 firefox 中运行良好,这是我在 Chrome 中获得的 headers:
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
我是不是遗漏了什么and/or我的代码有问题吗?
范围包括开始到结束。不是起始长度
例如:
Content-range: bytes 0-0/31491166
Returns 1 字节(从字节零到字节零)
您的代码不起作用,因为浏览器正在等待一个从未发送过的字节。
使用下面的代码片段。它在所有浏览器 Safari、Firefox 和 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;
}
}