java - spring mvc 框架上的流式 api 问题

标签 java html spring spring-mvc streaming

我正在编写一个 spring boot 应用程序,它具有 REST api(使用 spring mvc 框架),可将音频/视频流式传输到浏览器上的 HTML5 播放器。这些 API 支持内容的范围请求。

我遇到了一个问题,即 HTML5 视频播放器在流式传输期间定期报告错误 ERR_CONTENT_LENGTH_MISMATCH。

似乎从服务器接收到的字节与服务器在 Content-Length header 中通告的字节不匹配。

请告知造成这种情况的根本原因是什么。

到目前为止,我研究过的事情可能会解决该问题,但在我的案例中还没有:

没有缓冲响应。 tomcat前面没有apache。

这是我的代码:

@Api("Player API")

@RestController 公共(public)类 PlayerController {

@Autowired
FetchAssetService fetchAssetService;

@ApiOperation("Get video")
@RequestMapping(value = "player/video/{packageId}/{username}", method = RequestMethod.GET)
public ResponseEntity<StreamingResponseBody> getProxy(@RequestHeader(value="Range", required=false) String range, @PathVariable Long packageId, @PathVariable String username) throws Exception {
    Optional<Stream> videoAssetMetaData = fetchAssetService.fetchVideoAssetMetaData(packageId);
    if (!videoAssetMetaData.isPresent()) {
        throw new AssetNotFoundException("Video asset not found in MPL for package: "+packageId);
    }
    HttpHeaders httpHeaders = new HttpHeaders();
    HttpStatus status = HttpStatus.OK;
    Optional<AssetRange> optionalAssetRange = AssetRange.create(range,videoAssetMetaData.get().getLength());
    if (optionalAssetRange.isPresent()) {
        if (optionalAssetRange.get().isSatisfiable()) {
            setSuccessRangeHeaders(httpHeaders,optionalAssetRange.get());
            status = HttpStatus.PARTIAL_CONTENT;
        } else {
            setErrorRangeHeaders(httpHeaders,optionalAssetRange.get());
            status = HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE;
            return new ResponseEntity(null,httpHeaders,status);
        }
    }
    setContentHeaders(httpHeaders, “video.mp4");
    try {
        return new ResponseEntity(fetchAssetService.getStreamingResponseBody(packageId,videoAssetMetaData.get(),optionalAssetRange,username),
                httpHeaders,
                status);
    } catch (Exception ex) {
        log.error("Exception while video streaming: package={}, user={}, range={}",packageId,username,range,ex);
        throw ex;
    }
}

private void setContentHeaders(HttpHeaders httpHeaders, String fileName) {
    httpHeaders.add(HttpHeaders.ACCEPT_RANGES,"bytes");
    httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
    httpHeaders.add(HttpHeaders.CONTENT_DISPOSITION,"attachment; filename="+ fileName);
}

private void setSuccessRangeHeaders(HttpHeaders httpHeaders, AssetRange range) {
    httpHeaders.add(HttpHeaders.CONTENT_LENGTH, Long.toString(range.getRangeLength()));
    httpHeaders.add(HttpHeaders.CONTENT_RANGE, String.format("bytes %d-%d/%d", range.getStart(), range.getEnd(), range.getTotalLength()));
}

private void setErrorRangeHeaders(HttpHeaders httpHeaders, AssetRange range) {
    httpHeaders.add(HttpHeaders.CONTENT_RANGE, String.format("bytes */%d", range.getTotalLength()));
}

@ExceptionHandler(AssetNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public String handleAppException(AssetNotFoundException ex) {
    return ex.getMessage();
}

@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String handleAppException(Exception ex) {
    return ex.getMessage();
}

}

最佳答案

最佳猜测, 在 setSuccessRangeHeaders 中,您将内容长度设置为范围值,而不是响应的实际内容长度。

尝试根本不设置 content_length 或尝试更准确地设置它。

这可能有帮助: How to set content length as long value in http header in java?

关于java - spring mvc 框架上的流式 api 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35209276/

相关文章:

jquery - 如何在后台加载 36mb 视频

javascript - 如何改变球每次从墙上弹起的颜色?

java - Spring 中具有两个 id 的同一实例

html - 增加三 Angular 形的大小

java - 在 Jax-Ws 中使用 @Autowire 和 Spring 容器

java - 通过键名锁定数据库编辑

java - 如何在一定次数的执行后停止计划重复执行的 Runnable

java - addView方法不显示新 View

Java 泛型和多态性 - 如何在运行时缩小泛型类型范围

java - JSR303 自定义 validator 被调用两次