Jeśli mam plik na serwerze internetowym (Tomcat) i utworzę tag, mogę obejrzeć wideo, wstrzymać go, poruszać się po nim i ponownie uruchomić po jego zakończeniu.Jak mogę zwrócić wideo ze Spring MVC, aby można było nawigować za pomocą znacznika html5 <video>?
Ale jeśli utworzę interfejs REST, który wyśle plik wideo na żądanie, i doda jego adres URL do znacznika, mogę tylko odtwarzać i wstrzymywać. Bez przewijania, bez szybkiego przewijania do przodu, bez nawigacji, nic.
Czy istnieje sposób, aby to naprawić? Czy gdzieś czegoś brakuje?
Pliki wideo znajdują się na tym samym serwerze, co interfejs REST, a interfejs REST sprawdza tylko sesję i wysyła wideo po ustaleniu, który z nich należy wysłać.
Oto metody, które próbowałem do tej pory. Wszystkie działają, ale żaden z nich nie pozwala na nawigację.
Metoda 1, ResponseEntity:
/*
* This will actually load the whole video file in a byte array in memory,
* so it's not recommended.
*/
@RequestMapping(value = "/{id}/preview", method = RequestMethod.GET)
@ResponseBody public ResponseEntity<byte[]> getPreview1(@PathVariable("id") String id, HttpServletResponse response) {
ResponseEntity<byte[]> result = null;
try {
String path = repositoryService.findVideoLocationById(id);
Path path = Paths.get(pathString);
byte[] image = Files.readAllBytes(path);
response.setStatus(HttpStatus.OK.value());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentLength(image.length);
result = new ResponseEntity<byte[]>(image, headers, HttpStatus.OK);
} catch (java.nio.file.NoSuchFileException e) {
response.setStatus(HttpStatus.NOT_FOUND.value());
} catch (Exception e) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
return result;
}
Metoda 2, Stream Copy:
/*
* IOUtils is available in Apache commons io
*/
@RequestMapping(value = "/{id}/preview2", method = RequestMethod.GET)
@ResponseBody public void getPreview2(@PathVariable("id") String id, HttpServletResponse response) {
try {
String path = repositoryService.findVideoLocationById(id);
File file = new File(path)
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename="+file.getName().replace(" ", "_"));
InputStream iStream = new FileInputStream(file);
IOUtils.copy(iStream, response.getOutputStream());
response.flushBuffer();
} catch (java.nio.file.NoSuchFileException e) {
response.setStatus(HttpStatus.NOT_FOUND.value());
} catch (Exception e) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
}
Metoda 3, FileSystemResource:
@RequestMapping(value = "/{id}/preview3", method = RequestMethod.GET)
@ResponseBody public FileSystemResource getPreview3(@PathVariable("id") String id, HttpServletResponse response) {
String path = repositoryService.findVideoLocationById(id);
return new FileSystemResource(path);
}
Uważam, że filmów nie można nawigować, jeśli są one przesyłane strumieniowo, w przeciwieństwie do w pełni dostępnego pliku. Ale nie jestem tego pewien. – Calabacin
Uwielbiam trzecią metodę. Metoda 1 jest droga, a obie metody 1 i 2 naruszają wzorzec MVC (przy użyciu 'HttpServletResponse's' OutputStream'). Kontrolery powinny delegować zadania przeglądania do 'Widok' lub' HttpMessageConverter'. –
Niestety, żadna z nich nie była wystarczająco dobra do przesyłania strumieniowego wideo, ponieważ należy wziąć pod uwagę częściowe żądania http. Dodałem klasę kontrolera, która zarządzała tego rodzaju żądaniami całkowicie oddzielonymi od dowolnej usługi. – Calabacin