2016-02-04 59 views
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(); 
} 

}

回答