如何使用Servlet流式传输音频/视频文件,例如MP3、MP4、AVI等

13
我想使用servlet将我的音视频文件流式传输到网络上。 我尝试使用以下servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    File file = new File("/Users/myfolder/Documents/workspace/love.mp3");
    response.setContentType(getServletContext().getMimeType(file.getName()));
    response.setContentLength((int) file.length());
    Files.copy(file.toPath(), response.getOutputStream());
}

并且以下是HTML代码:

<a href="/media" data-format="mp3 ogg">Click Here!</a>

然而,玩家正在加载......加载......加载......

这是由什么原因引起的,我该如何解决?

1个回答

24
许多媒体播放器要求服务器支持所谓的HTTP范围请求。也就是说,它必须能够返回带有Range标头的请求中媒体文件的特定部分。例如,仅在长度为10MB的文件上,从索引1000到2000的字节。这对于许多媒体播放器来说是强制性的,以便能够足够快地跳过媒体流的某个范围和/或通过创建每个请求文件不同部分的多个连接来提高缓冲速度。
然而,这需要您的servlet中有大量额外的代码,并且需要对HTTP Range规范有很好的理解。通常,Servlet容器(Tomcat、JBoss AS、Glassfish等)自己的默认Servlet已经支持此功能。因此,如果有一种通过标准手段将媒体文件夹发布到Web上的方法,以便您不需要自己编写一个servlet,则可以选择这种方法。

不清楚您使用的是哪个Servlet容器,因此在本示例中我假设使用Tomcat:

  1. Just drop love.mp3 file in the public web content of the web project, so that it's just available by <a href="love.mp3"> without the need for a whole servlet.

  2. Or, put the love.mp3 file in a new subfolder of Tomcat/webapps folder, e.g. Tomcat/webapps/media/love.mp3. This way it's available by <a href="/media/love.mp3">.

  3. Or, put the love.mp3 file elsewhere on disk, e.g. /path/to/media/love.mp3 and add the /media folder as new context by adding the following line to Tomcat's /conf/server.xml:

     <Context docBase="/path/to/media" path="/media" />
    

    This way it's available by <a href="/media/love.mp3"> as well.

无论如何,Tomcat会使用自己的DefaultServlet来流式传输内容,该Servlet支持Range请求。
如果绝对没有办法使用servlet容器自带的默认servlet,那么您需要重写您的servlet代码,以便正确支持Range请求。您可以从开源示例中获取灵感,例如Tomcat DefaultServletOmniFaces FileServlet

另请参阅:


抱歉,我错过了重要信息。这不是路径问题...因为当我在没有HTML5音频播放器(可访问音频播放器)的情况下运行服务器时,它完全可以工作。我想要的是使用servlet流式传输到html5播放器。 - Likoed
是的,我知道。你读过理解我的答案了吗?你的servlet必须支持Range请求。然而,servlet容器的默认servet已经支持它,所以最好直接通过将文件直接发布到Web来利用它。 - BalusC
好的。谢谢你的回答,但是似乎需要时间来理解。我会尝试一下。 - Likoed
1
有没有办法为DefaultServlet提供的静态内容实现请求过滤器? - jwi
@jwi 你可以编写一个过滤器,它执行到 DefaultServlet转发,然后在此之后未调用 chain.doFilter(request, response) - Christopher Schultz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接