¿Cómo devuelvo un video con Spring MVC para que pueda navegar usando la etiqueta html5 ?

Si tengo un archivo en el servidor web (Tomcat) y creo una etiqueta, puedo ver el video, pausarlo, navegarlo y reiniciarlo cuando termine.

Pero si creo una interfaz REST que envía el archivo de video cuando se solicita y agrego su URL a una etiqueta, solo puedo reproducir y pausar. Sin rebobinado, sin avance rápido, sin navegación , nada.

Entonces, ¿hay alguna manera de arreglar esto? ¿Me estoy perdiendo algo en algún lado?

Los archivos de video están en el mismo servidor que la interfaz REST , y la interfaz REST solo comprueba la sesión y envía el video después de descubrir cuál debe enviar.

Estos son los métodos que he probado hasta ahora. Todos funcionan, pero ninguno permite navegar.

Método 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 getPreview1(@PathVariable("id") String id, HttpServletResponse response) { ResponseEntity 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(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; } 

Método 2, copia de Stream:

 /* * 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()); } } 

Método 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); } 

La función de descarga de currículum HTTP puede ser tu amiga. Yo tuve el mismo problema antes. Después de implementar el rango http, la navegación en el video fue posible:

http://balusc.blogspot.com/2009/02/fileservlet-supporting-resume-and.html

Una solución simple para manejar recursos no estáticos :

 @SpringBootApplication public class DemoApplication { private final static File MP4_FILE = new File("/home/ego/bbb_sunflower_1080p_60fps_normal.mp4"); public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Controller final static class MyController { @Autowired private MyResourceHttpRequestHandler handler; // supports byte-range requests @GetMapping("/") public void home( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { request.setAttribute(MyResourceHttpRequestHandler.ATTR_FILE, MP4_FILE); handler.handleRequest(request, response); } // does not support byte-range requests @GetMapping(path = "/plain", produces = "video/mp4") public FileSystemResource plain() { return new FileSystemResource(MP4_FILE); } } @Component final static class MyResourceHttpRequestHandler extends ResourceHttpRequestHandler { private final static String ATTR_FILE = MyResourceHttpRequestHandler.class.getName() + ".file"; @Override protected Resource getResource(HttpServletRequest request) throws IOException { final File file = (File) request.getAttribute(ATTR_FILE); return new FileSystemResource(file); } } } 

(inspirado en Spring Boots LogFileMvcEndpoint y más o menos igual a Paul-Warrens (@ paul-warren) StoreByteRangeHttpRequestHandler que encontré más adelante).

Esperemos que esto sea algo que Spring respaldará en el futuro cercano, consulte https://jira.spring.io/browse/SPR-13834 (vote por él).

Sé que esta es una publicación anterior, pero en caso de que sea útil para alguien más que haga las mismas preguntas o similares.

Hoy en día hay proyectos como Spring Content que admiten de forma nativa la transmisión de video. Todo el código que necesitaría para la implementación más simple sería:

 @StoreRestResource(path="videos") public interface VideoStore extends Store {} 

Y esto sería suficiente para crear una API Java y un conjunto de puntos finales REST que le permitieran PUT / POST, GET y ELIMINAR secuencias de video. GET admite rangos de bytes y se reproducirá correctamente en reproductores de video HTML5 y cosas por el estilo.

De hecho, es el front-end quien muestra los controles de video para la etiqueta

Cada navegador para un formato de video especial, tiene un panel de control predeterminado.

Puede usar html y css para crear su propio control con API de medios. Api de medios

De Div a HTML5 [De forma predeterminada, el elemento

    Intereting Posts