Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java spring mvc框架上的流式API问题_Java_Html_Spring_Spring Mvc_Streaming - Fatal编程技术网

Java spring mvc框架上的流式API问题

Java spring mvc框架上的流式API问题,java,html,spring,spring-mvc,streaming,Java,Html,Spring,Spring Mvc,Streaming,我正在编写一个SpringBoot应用程序,它有RESTAPI(使用SpringMVC框架),可以将音频/视频流到浏览器上的HTML5播放器。这些API支持内容的范围请求 我遇到了一个问题,HTML5视频播放器在流媒体播放期间周期性地抱怨错误ERR_CONTENT_LENGTH_失配 从服务器接收的字节似乎与服务器在Content Length标头中公布的字节不匹配 请告知这可能的根本原因 到目前为止,我所研究的可能解决问题但在我的案例中没有解决的东西: 没有缓冲响应。 tomcat前面没有ap

我正在编写一个SpringBoot应用程序,它有RESTAPI(使用SpringMVC框架),可以将音频/视频流到浏览器上的HTML5播放器。这些API支持内容的范围请求

我遇到了一个问题,HTML5视频播放器在流媒体播放期间周期性地抱怨错误ERR_CONTENT_LENGTH_失配

从服务器接收的字节似乎与服务器在Content Length标头中公布的字节不匹配

请告知这可能的根本原因

到目前为止,我所研究的可能解决问题但在我的案例中没有解决的东西:

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

这是我的密码:

@Api("Player API")
@RestController 公共类播放控制器{

@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();
}
@Autowired
FetchAssetService FetchAssetService;
@API操作(“获取视频”)
@RequestMapping(value=“player/video/{packageId}/{username}”,method=RequestMethod.GET)
public ResponseEntity getProxy(@RequestHeader(value=“Range”,required=false)字符串范围、@PathVariable Long packageId、@PathVariable字符串用户名)引发异常{
可选videoAssetMetaData=fetchAssetService.fetchVideoAssetMetaData(packageId);
如果(!videoAssetMetaData.isPresent()){
抛出新的AssetNotFoundException(“在包的MPL中找不到视频资产:“+packageId”);
}
HttpHeaders HttpHeaders=新的HttpHeaders();
HttpStatus status=HttpStatus.OK;
可选选项AssetRange=AssetRange.create(范围,videoAssetMetaData.get().getLength());
if(可选AssetTransge.isPresent()){
if(可选AssetTrange.get().IsSatifiable()){
setSuccessRangeHeaders(httpHeaders,optionalAssetRange.get());
状态=HttpStatus.PARTIAL\u内容;
}否则{
setErrorRangeHeaders(httpHeaders,optionalsassetrange.get());
状态=HttpStatus.REQUESTED\u RANGE\u不可满足;
返回新的ResponseEntity(null,httpHeaders,status);
}
}
setContentHeaders(httpHeaders,“video.mp4”);
试一试{
返回新的ResponseEntity(fetchAssetService.getStreamingResponseBody(packageId,videoAssetMetaData.get(),OptionalAssetTransage,用户名),
HttpHeader,
地位);
}捕获(例外情况除外){
log.error(“视频流时异常:包={},用户={},范围={}”,包ID,用户名,范围,ex);
掷骰子;
}
}
私有void setContentHeaders(HttpHeaders HttpHeaders,字符串文件名){
添加(httpHeaders.ACCEPT_范围,“字节”);
添加(httpHeaders.CONTENT\u TYPE、MediaType.APPLICATION\u OCTET\u STREAM\u VALUE);
添加(httpHeaders.CONTENT_处置,“附件;文件名=”+filename);
}
私有void setSuccessRangeHeaders(HttpHeaders HttpHeaders,AssetRange范围){
添加(httpHeaders.CONTENT_LENGTH,Long.toString(range.getRangeLength());
添加(httpHeaders.CONTENT_RANGE,String.format(“字节%d-%d/%d”,RANGE.getStart(),RANGE.getEnd(),RANGE.getTotalLength());
}
私有void setErrorRangeHeaders(HttpHeaders HttpHeaders,AssetRange){
添加(httpHeaders.CONTENT_RANGE,String.format(“bytes*/%d”,RANGE.getTotalLength());
}
@ExceptionHandler(AssetNotFoundException.class)
@ResponseStatus(未找到HttpStatus.NOT_)
公共字符串handleAppException(AssetNotFoundException ex){
返回例如getMessage();
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL\u SERVER\u错误)
公共字符串handleAppException(异常ex){
返回例如getMessage();
}
}最佳猜测, 在setSuccessRangeHeaders中,您将内容长度设置为范围值,而不是响应的实际内容长度

尝试完全不设置内容长度,或者尝试更准确地设置内容长度

这可能有助于: 最佳猜测, 在setSuccessRangeHeaders中,您将内容长度设置为范围值,而不是响应的实际内容长度

尝试完全不设置内容长度,或者尝试更准确地设置内容长度

这可能有助于:

谢谢你的回答!谢谢你的回答!