为了账号安全,请及时绑定邮箱和手机立即绑定

如果传输状态为 206 部分内容,Chrome 将无法加载视频

如果传输状态为 206 部分内容,Chrome 将无法加载视频

万千封印 2023-04-26 14:24:49
我正在制作一个简单的 Javacom.sun.net.httpserver.HttpServer来提供静态视频文件。如果我返回状态代码 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 中获得的标头:Response Headers:Accept-range: bytesContent-length: 31491166Content-range: bytes 0-31491166/31491166Content-type: video/mp4Date: Sat, 27 Jul 2019 14:32:55 GMTTransfer-encoding: chunked我是否遗漏了什么和/或我的代码有什么问题?
查看完整描述

2 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

范围包括开始到结束。不是起始长度

例如:

Content-range: bytes 0-0/31491166

返回 1 个字节(从字节零到字节零)

您的代码不起作用,因为浏览器正在等待一个从未发送过的字节。


查看完整回答
反对 回复 2023-04-26
?
噜噜哒

TA贡献1784条经验 获得超7个赞

使用下面的代码片段。它在所有浏览器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;

    }

}


查看完整回答
反对 回复 2023-04-26
  • 2 回答
  • 0 关注
  • 784 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信