문제점
해결방안
구현
@Override
public ResponseEntity<ResourceRegion> sendMediaVideo(int mediaNo,String userId,HttpHeaders headers) throws Exception{
MediaDto media=mediaMapper.selectByMediaNo(mediaNo);
if(media==null) {
throw new MediaException(MediaErrorCode.NotFoundMedia.getCode(),MediaErrorCode.NotFoundMedia.getDescription());
}
if(!"video".equals(media.getMediaType())){
throw new MediaException(MediaErrorCode.NotCorrectType.getCode(),MediaErrorCode.NotCorrectType.getDescription());
}
String filePath=uploadPath+ File.separator+media.getSavePath();
if(!Files.exists(Paths.get(filePath))) {
throw new FileException(FileErrorCode.NotFoundFile.getCode(),FileErrorCode.NotFoundFile.getDescription());
}
Resource resource = new FileSystemResource(filePath);
ResourceRegion region=getVideoRegion(resource,headers);
return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
.contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
.header("Accept-Ranges", "bytes")
.eTag(media.getMediaOriginFile())
.body(region);
}
private ResourceRegion getVideoRegion(Resource resource,HttpHeaders headers) throws Exception{
long contentLength = resource.contentLength();
ResourceRegion region;
try {
//헤더로부터 모든 인자 추출하기
HttpRange httpRange = headers.getRange().stream().findFirst().get();
long start = httpRange.getRangeStart(contentLength);
long end = httpRange.getRangeEnd(contentLength);
//최대 chunksize만큼 길이 설정
long rangeLength = Long.min(this.chunkSize, end -start + 1);
//start부터 rangeLength만큼 전송
region = new ResourceRegion(resource, start, rangeLength);
} catch (Exception e) {
//중간에 에러가 난다면 처음부터 끝까지의 데이터 전송
long rangeLength = Long.min(this.chunkSize, contentLength);
region = new ResourceRegion(resource, 0, rangeLength);
}
return region;
}
chunk_size(2.1MB)씩 부분적으로 가져오고 있다.