13

I would like to stream my audio/video files to web using servlet.

I made an attempt with the following 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());
}

And the following HTML:

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

However, the player is just loading... loading... loading...

How is this caused and how can I solve it?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Likoed
  • 533
  • 2
  • 5
  • 15

1 Answers1

24

A lot of media players require that the server supports the so-called HTTP range requests. I.e. it must be able to return specific parts of the media file on request with a Range header. For example, only the bytes at exactly the index 1000 until with 2000 on a file of 10MB long. This is mandatory for many media players in order to be able to skip a certain range of the media stream quickly enough and/or to improve buffering speed by creating multiple connections which each requests different parts of the file.

This is however a lot of additional code in your servlet which requires a well understanding of the HTTP Range specification. Usually the servletcontainer's (Tomcat, JBoss AS, Glassfish, etc) own default servlet already supports this out the box. So if there's a way to publish the media folder into the web by standard means, so that you don't need to homegrow a servlet for this, then I'd go on this route.

It's unclear which servletcontainer you're using, so I'll assume Tomcat in this example:

  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.

Either way, Tomcat's own DefaultServlet, which has proper support for Range requests, will be used to stream the content.

But if there's absolutely no way to make use of servletcontainer's own default servlet, then you need to rewrite your servlet code in such way that it properly supports Range requests. You can get inspiration from open source examples such as Tomcat DefaultServlet and OmniFaces FileServlet.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • sorry. I missed important information. It's not path problem... because It completely works when I ran server without HTML5 Audio Player(Accessible Audio Player). What I want is streaming to html5 player with servlet. – Likoed Nov 27 '12 at 23:44
  • Yes, I know that. Have you *read* and *understood* my answer? Your servlet must support `Range` requests. The servletcontainer's default servet however already supports it out the box, so it's much more preferable to just make use of it by publishing the file directly to the web. – BalusC Nov 27 '12 at 23:45
  • OK.. Thanks to your answer but it seems to need time to understand. I will try it. – Likoed Nov 28 '12 at 05:07
  • 1
    Is there a way I can implement a request filter for static content which is served by the DefaultServlet? – jwi Sep 06 '17 at 13:10
  • @jwi You can write a filter which performs a *forward* to the `DefaultServlet`, then fails to call `chain.doFilter(request, response)` afterward. – Christopher Schultz Aug 03 '20 at 03:34