1
我正在寫一個彈簧啓動應用程序,它具有REST apis(使用spring mvc框架),可將音頻/視頻流傳輸到瀏覽器上的HTML5播放器。這些apis支持範圍內容請求。彈簧mvc框架上流API的問題
我遇到了一個問題,即HTML5視頻播放器在流式傳輸期間定期錯誤ERR_CONTENT_LENGTH_MISMATCH進行投訴。
似乎從服務器收到的字節不匹配服務器在Content-Length標頭中發佈的字節。
請告知這可能是什麼原因。
的事情,我至今可能潛在地解決這個問題,但在我的情況還沒有研究:
響應無緩衝。 在tomcat前面沒有apache。
這裏是我的代碼:
@Api("Player API")
@RestController 公共類的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();
}
}
感謝您的回答! –