HTTP range requests
HTTP 범위 요청이란 HTTP 를 통해 일정한 부분을 서버에서 클라이언트로 보내는 것을 Accept하고 보내는 방법입니다. 범위를 알 수 있는 대형 미디어 파일을 나누어서 읽을 수 있습니다. 파일 다운로드 도중 일시정지와 다시 시작 기능에 유용한 점을 이용해 클라이언트에선 미디어파일을 재생, 일시정지, 다시시작을 가능하게 만들 수 있습니다. 예를 들어 4.5mb짜리 파일을 받겠다하면, 서버는 전체 범위(Content-Length
)와 일정 범위에 해당하는 파일을 bytes 로 내려보내줍니다.
참고
HTML5 Video
Tag
HTML5 <video>
는 HTTP range request를 사용하는 대표적인 태그입니다. 비슷하게는 <audio>
도 존재합니다.<video>
속성 태그로는 <source>
와 <track>
를 사용할 수 있으며, <source>
는 데이터의 유형을 나타내고 <track>
은 재생 중 표시할 자막, 캡션 파일, 텍스트를 포함하는 파일을 표시할 수 있습니다.
참고
Spring Http Range Request 처리
Controller
@GetMapping("/videos/{name}")
public ResponseEntity<ResourceRegion> getVideo(@PathVariable String name,
@RequestHeader HttpHeaders headers) throws IOException {
log.info("getVideo");
UrlResource video = new UrlResource("classpath:" + videoLocation + "/" + name);
ResourceRegion region = resourceRegion(video, headers);
return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
.contentType(MediaTypeFactory.getMediaType(video).orElse(MediaType.APPLICATION_OCTET_STREAM))
.body(region);
}
MediaTypeFactory
를 통해 파일의 content-type
의 유형을 가져오거나, 기본값으로 8 bit 스트림 유형인 APPLICATION_OCTET_STREAM
리턴합니다.
잘 보시면 body
에 ResouceRegion
객체를 담아 보내는데요. ResourceRegion
은 파일 객체의 Range
범위 만큼을 가져올 수 있는 스프링 코어 객체입니다.
ResourceRegion
private ResourceRegion resourceRegion(UrlResource video, HttpHeaders headers) throws IOException {
final long chunkSize = 1000000L;
long contentLength = video.contentLength();
HttpRange httpRange = headers.getRange().stream().findFirst().get();
if(httpRange != null) {
long start = httpRange.getRangeStart(contentLength);
long end = httpRange.getRangeEnd(contentLength);
long rangeLength = Long.min(chunkSize, end - start + 1);
return new ResourceRegion(video, start, rangeLength);
} else {
long rangeLength = Long.min(chunkSize, contentLength);
return new ResourceRegion(video, 0, rangeLength);
}
}
처음 요청(else
구문) 은 chunk 사이즈로 자른 시작값부터 청크 사이즈 만큼의 ResoureRegion
을 return
하고 그 다음 요청은 header
에 담긴 range
범위만큼 짤라 보냅니다.
- https://melgenek.github.io/spring-video-service
- https://developer.mozilla.org/ko/docs/Web/HTTP/Status/206
클라이언트 요청과 응답은 아래와 같습니다.
Request에서는 bytes=1557056 과 같이 범위 요청이 일어난 것을 볼 수 있습니다.
Response에서는 Content-Type 은 video/mp4로 리턴되고, 청크 싸이즈만큼 컨텐츠 사이즈가 정해진 것을 볼 수 있습니다.
서버는 각 요청을 지속적으로 받기 때문에 각기 다른 쓰레드로 처리된 것을 확인할 수 있습니다.
파일사이즈 만큼 클라이언트가 범위요청한 내역입니다. HTTP code 206 상태는 분활 스트리밍 상태에서 정상응답 코드입니다.
Github 주소
위 예제는 중요 파트만 잘라 놓았음으로 자세한 소스를 보고 싶으시다면 아래 링크를 참고하세요.
https://github.com/Derveljun/derveljun-video-streaming
'Java & Spring' 카테고리의 다른 글
[트러블 슈팅] Jstack 을 통한 Thread Dump 및 분석 (0) | 2021.12.28 |
---|---|
JAVA 1.8 환경에서 MSSQL 접속 시 에러 해결 (0) | 2021.12.01 |
스프링 javax 에러 / 구형 스프링 프로젝트 javax 문제 / (0) | 2021.12.01 |
스프링 배치 Spring Batch [2] Hello Spring Batch 실행해보기 (0) | 2020.01.27 |
[Netty] Shared 된 ChannelHandler 사용시 Message 처리 (0) | 2017.01.27 |
WRITTEN BY