- mp4 같은 동영상을 스트리밍하는 경우와 다운로드를 동시에 처리하는 리소스가 없어서 이것저것 살펴보면서 작성함.
- 스트리밍요청과 다운로드 요청을 구분하여 처리하는게 필요함.
- 브라우저에서 여러번 요청을 받아서 처리해야 하므로 InputStreamResource 이 아닌 FileSystemResource 를 사용해야 함
@RequestMapping(value = "/api/file/download/{filepath}"
, method = RequestMethod.GET
, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<ResourceRegion> getMp4StreamingAndDownload(@RequestHeader(value = "Range", required = false) String httpRangeList, @PathVariable String filepath, @PathVariable String value, @RequestHeader HttpHeaders headers)
throws IOException {
String fileFullPath = ""; // 스트리밍할 리소스 경로.
Optional<HttpRange> httpRangeOptional = headers.getRange().stream().findFirst();
if (httpRangeOptional.isPresent() == false) {
// 다운로드 요청시에.
Resource resource = new FileSystemResource(new File(fileFullPath));
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.cacheControl(CacheControl.noCache())
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=video.mp4")
.body(new ResourceRegion(resource, 0, resource.contentLength()));
} else {
// 스트리밍 요청시에...
Resource resource = new FileSystemResource(new File(fileFullPath));
long chunkSize = 1024 * 1024;
long contentLength = resource.contentLength();
ResourceRegion region = null;
try {
HttpRange httpRange = httpRangeOptional.get();
long start = httpRange.getRangeStart(contentLength);
long end = httpRange.getRangeEnd(contentLength);
long rangeLength = Long.min(chunkSize, end - start + 1);
region = new ResourceRegion(resource, start, rangeLength);
} catch (Exception e) {
long rangeLength = Long.min(chunkSize, contentLength);
region = new ResourceRegion(resource, 0, rangeLength);
}
return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
.cacheControl(CacheControl.maxAge(10, TimeUnit.MINUTES))
.contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
.header("Accept-Ranges", "bytes")
.eTag(fileFullPath)
.body(region);
}