通过Servlet向客户端输出文件

大力:“昨天晚上我在家看了你在知乎上发布的最新Java视频课程,讲得真精彩!。”

卫琴姐:“当你喝着茶,悠哉游哉听我讲课时,你知道浏览器和服务器有多么忙碌吗?”

大力:“服务器要把视频数据发送给浏览器,浏览器收到后,要把它播放给我看。”

Web服务器除了向浏览器发送HTML文档,还可以向浏览器发送其他格式的响应正文,包括图片文件、声音文件、视频文件和压缩文件等。浏览器会把这些文件保存到本地文件系统中,这一过程称为下载文件。浏览器还会根据HTML代码中的<img>元素来展示图片,根据<audio>元素播放声音,以及根据<video>元素播放视频。

例程1的DownloadServlet类演示服务器向客户端发送声音文件。它先读取请求参数filename,该参数代表客户端请求访问的文件的名字。DownloadServlet类接下来通过ServletContext的getResourceAsStream()方法,得到一个用于读取helloapp/resource目录下的相应文件的输入流,再调用response.getOutputStream()方法,得到一个用于输出响应正文的输出流。DownloadServlet类然后通过输入流读取文件中的数据,并通过输出流把文件中的数据发送到客户端。

例程1 DownloadServlet.java

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
  public void doGet(HttpServletRequest request,
         HttpServletResponse response)
         throws ServletException, IOException {
    OutputStream out;     // 输出响应正文的输出流
    InputStream in;       // 读取本地文件的输入流
    // 获得filename请求参数 
    String filename=request.getParameter("filename");
    if(filename==null){
      out=response.getOutputStream(); 
      out.write("Please input filename.".getBytes());
      out.close();
      return;
    //获得读取本地文件的输入流
    in= getServletContext()
                .getResourceAsStream("/resource/"+filename);
    int length=in.available();
    // 设置响应正文的MIME类型
    response.setContentType("audio/x-mpeg"); 
    response.setHeader("Content-Length",
                           String.valueOf(length));
    // 把本地文件中的数据发送到客户端 
    out=response.getOutputStream(); 
    int bytesRead = 0;
    byte[] buffer = new byte[512];
    while ((bytesRead = in.read(buffer)) != -1){
      out.write(buffer, 0, bytesRead);
    in.close();
    out.close();
}

DownloadServlet类把响应正文的MIME类型设为表示声音数据的“audio/x-mpeg”,这一信息存放在响应头中。浏览器收到这种MIME类型的响应正文时,默认情况下,会以下载的方式来处理响应正文,参见图1。

图1 DownloadServlet类把声音文件发送给客户端

通过浏览器访问http://localhost:8080/helloapp/download?filename=morning.mp3,浏览器会把morning.mp3文件下载到本地文件系统中。

如果希望浏览器播放morning.mp3文件,可以在一个HTML文档中通过<audio>元素来播放它。例程2的music.html的页面上有一个下拉菜单,当用户选择了一首歌曲,<audio>元素就会播放该歌曲。

例程2 music.html

<form name="myform">
   选择歌曲
  <select name="menu" onclick="changeMusic()">
    <option value="morning.mp3">晨曲</option>
    <option value="lotus.mp3">静心曲</option>
  </select><br><br>
  <audio id="player" 
          src="download?filename=morning.mp3" controls>
  </audio>
</form>
<script>
window.onload= changeMusic();
function changeMusic() {
  var music;  // 用户选中的歌曲
  for(var i=0;i<myform.menu.length;i++){
    if(myform.menu[i].selected)
      music=myform.menu[i].value;
  var player=document.getElementById("player");