Spring Boot + Video 错误“由于网络错误导致视频播放中止”

Posted

技术标签:

【中文标题】Spring Boot + Video 错误“由于网络错误导致视频播放中止”【英文标题】:Spring Boot + Video error "video playback aborted due to a network error" 【发布时间】:2019-02-21 05:37:59 【问题描述】:

所以我设计了一个应用程序,它有一个 reactjs 前端,用于提供来自 Spring Boot 后端的内容。我有一个提供视频的休息控制器。它运行了大约 10 分钟,然后在我的浏览器中出现“由于网络错误导致视频播放中止”。我在这里做错了吗?这应该在另一个线程或异步或其他东西上完成吗?我想这一切都在春天完成了。

@RestController
@CrossOrigin
public class VideoDirectoryController 
@Autowired
private ConfigManager<LibraryConfig> librariesConf;

/**
 * 
 * @param libraryName
 * @param fileName
 * @return
 */
@GetMapping(value = "/getVideo", produces = "video/mp4")
public byte[] getVideo(@RequestParam(value = "library") String libraryName,
        @RequestParam(value = "fileName") String fileName) 
    Library lib = librariesConf.getConfig().getLibraries().get(libraryName.toLowerCase());
    Video video = lib.getVideoFiles().get(fileName);
    lib.getRecentlyViewed().add(video);
    librariesConf.getConfig().getLibraries().keySet().forEach((libr) -> System.out.println("LIBR: :" + libr));
    try (FileInputStream out = new FileInputStream(lib.getFileDirectory(fileName))) 
        return IOUtils.toByteArray(out);
     catch (IOException e) 
        e.printStackTrace();
    
    return null;

正如我所说,这可以正常工作大约 10 分钟。如果我使用 :3000 (前端)和直接点击获取视频的 URL (:8080/getVideo)

感谢任何帮助我以前从未在 Spring Boot 中使用过多媒体。

【问题讨论】:

对于初学者,不要读取内存中的所有内容然后返回给客户端。相反,恕我直言,您应该将内容流式传输给用户。所以注入HttpServletResponse,直接写入内容而不是读入内存。 谢谢@M.Deinum 您如何看待 StreamingResponseBody?这是使用 IOUtils.copy 并启用 AsyncTaskExecutor 向我提出的其他建议。你认为这样做会有什么问题吗?也肯定是因为它使用的是OutputStream Spring按需流而不是将其全部推送到内存中?我觉得如果一次将 10GB 视频文件全部加载到内存中,它不会立即加载。我的电脑速度很快,但……没那么快。 我正在写一个答案。两者都行。 【参考方案1】:

我建议使用StreamingResponseBody 或直接写信给HttpServletRequestOutputStream。连同设置响应的内容类型和大小。

@GetMapping(value = "/getVideo", produces = "video/mp4")
public void getVideo(@RequestParam(value = "library") String libraryName,
        @RequestParam(value = "fileName") String fileName, HttpServletResponse response) 
    Library lib = librariesConf.getConfig().getLibraries().get(libraryName.toLowerCase());
    Video video = lib.getVideoFiles().get(fileName);
    lib.getRecentlyViewed().add(video);
    librariesConf.getConfig().getLibraries().keySet().forEach((libr) -> System.out.println("LIBR: :" + libr));

    try (FileInputStream out = new FileInputStream(lib.getFileDirectory(fileName))) 
        return StreamUtils.copy(out, response.getOutputStream());
     catch (IOException e) 
        e.printStackTrace();
    

或者同样使用StreamingResponseBody

@GetMapping(value = "/getVideo", produces = "video/mp4")
public StreamingResponseBody getVideo(@RequestParam(value = "library") String libraryName,
        @RequestParam(value = "fileName") String fileName) 
    Library lib = librariesConf.getConfig().getLibraries().get(libraryName.toLowerCase());
    Video video = lib.getVideoFiles().get(fileName);
    lib.getRecentlyViewed().add(video);
    librariesConf.getConfig().getLibraries().keySet().forEach((libr) -> System.out.println("LIBR: :" + libr));
    return new StreamingResponseBody() 
        public void write(OutputStream out2) throws IOException 
            try (FileInputStream out = new FileInputStream(lib.getFileDirectory(fileName))) 
                StreamUtils.copy(out, out2);       
            
        
    ;

【讨论】:

以上是关于Spring Boot + Video 错误“由于网络错误导致视频播放中止”的主要内容,如果未能解决你的问题,请参考以下文章

由于 kotlin 错误,Java Spring Boot 应用程序无法从 IDEA 运行

由于maven插件错误,spring boot maven项目未编译

由于错误的数据库访问凭据,spring boot war 打包失败

端口6000无法访问Spring Boot Swagger REST服务器由于localhost不安全错误

为 Spring Boot 实现字节服务

Spring Boot 休息 API