【问题标题】:Video Using HTML 5 and servlet使用 HTML 5 和 servlet 的视频
【发布时间】:2012-01-25 08:58:24
【问题描述】:

下面给出的代码用于视频流。这对 IE9 和 firefox 很好,但对 Chrome 和 Mac Safari 就不好了。

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class VideoStreamServlet
 */

public class VideoStreamServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * Default constructor. 
     */
    public VideoStreamServlet() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        String range = request.getHeader("range");
        String browser = request.getHeader("User-Agent");
        System.out.println(browser);
        if(browser.indexOf("Firefox") != -1){
            System.out.println("==========ITS FIREFOX=============");
            byte[] data = getBytesFromFile(new File("D:/media/final.ogg"));
            response.setContentType("video/ogg");
            response.setContentLength(data.length);
            response.setHeader("Content-Range", range + Integer.valueOf(data.length-1));
            response.setHeader("Accept-Ranges", "bytes");
            response.setHeader("Etag", "W/\"9767057-1323779115364\"");
            byte[] content = new byte[1024];
            BufferedInputStream is = new BufferedInputStream(new ByteArrayInputStream(data));
            OutputStream os = response.getOutputStream();
            while (is.read(content) != -1) {
                //System.out.println("... write bytes");
                os.write(content);
            }
            is.close();
            os.close();
        }

        else if(browser.indexOf("Chrome") != -1){
            System.out.println("==========ITS Chrome=============");
            byte[] data = getBytesFromFile(new File("D:/media/final.mp4"));
            String diskfilename = "final.mp4";
            response.setContentType("video/mp4");
            //response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + diskfilename + "\"" );
            System.out.println("data.length " + data.length);
            response.setContentLength(data.length);
            response.setHeader("Content-Range", range + Integer.valueOf(data.length-1));
            response.setHeader("Accept-Ranges", "bytes");
            response.setHeader("Etag", "W/\"9767057-1323779115364\"");
            byte[] content = new byte[1024];
            BufferedInputStream is = new BufferedInputStream(new ByteArrayInputStream(data));
            OutputStream os = response.getOutputStream();
            while (is.read(content) != -1) {
                //System.out.println("... write bytes");
                os.write(content);
            }
            is.close();
            os.close();
        }

        else if(browser.indexOf("MSIE") != -1) {
            System.out.println("==========ITS IE9=============");
            byte[] data = getBytesFromFile(new File("D:/media/final.mp4"));
            String diskfilename = "final.mp4";
            response.setContentType("video/mpeg");
            //response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + diskfilename + "\"" );
            System.out.println("data.length " + data.length);
            response.setContentLength(data.length);
            response.setHeader("Content-Range", range + Integer.valueOf(data.length-1));
            response.setHeader("Accept-Ranges", "text/x-dvi");
            response.setHeader("Etag", "W/\"9767057-1323779115364\"");
            byte[] content = new byte[1024];
            BufferedInputStream is = new BufferedInputStream(new ByteArrayInputStream(data));
            OutputStream os = response.getOutputStream();
            while (is.read(content) != -1) {
                //System.out.println("... write bytes");
                os.write(content);
            }
            is.close();
            os.close();
        }
        else if( browser.indexOf("CoreMedia") != -1) {
            System.out.println("============ Safari=============");
            byte[] data = getBytesFromFile(new File("D:/media/final.mp4"));
            String diskfilename = "final.mp4";
            response.setContentType("video/mpeg");
            //response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + diskfilename + "\"" );
            System.out.println("data.length " + data.length);
            //response.setContentLength(data.length);
            //response.setHeader("Content-Range", range + Integer.valueOf(data.length-1));
           // response.setHeader("Accept-Ranges", " text/*, text/html, text/html;level=1, */* ");
           // response.setHeader("Etag", "W/\"9767057-1323779115364\"");
            byte[] content = new byte[1024];
            BufferedInputStream is = new BufferedInputStream(new ByteArrayInputStream(data));
            OutputStream os = response.getOutputStream();
            while (is.read(content) != -1) {
                //System.out.println("... write bytes");
                os.write(content);
            }
            is.close();
            os.close();
        }
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
    }   
     private static byte[] getBytesFromFile(File file) throws IOException {
        InputStream is = new FileInputStream(file);
        //System.out.println("\nDEBUG: FileInputStream is " + file);
        // Get the size of the file
        long length = file.length();
        //System.out.println("DEBUG: Length of " + file + " is " + length + "\n");
        /*
         * You cannot create an array using a long type. It needs to be an int
         * type. Before converting to an int type, check to ensure that file is
         * not loarger than Integer.MAX_VALUE;
         */
        if (length > Integer.MAX_VALUE) {
            System.out.println("File is too large to process");
            return null;
        }
        // Create the byte array to hold the data
        byte[] bytes = new byte[(int)length];
        // Read in the bytes
        int offset = 0;
        int numRead = 0;
        while ( (offset < bytes.length)
                &&
                ( (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) ) {
            offset += numRead;
        }
        // Ensure all the bytes have been read in
        if (offset < bytes.length) {
            throw new IOException("Could not completely read file " + file.getName());
        }
        is.close();
        return bytes;
    }

}

【问题讨论】:

  • 一些注意事项:您所做的不是“流式传输”,您只是通过 HTTP 像其他任何方式一样提供文件;在服务器级别处理不同的浏览器是一个非常糟糕的主意(通常应该尽可能少地完成);您应该只将每种情况不同的 2-3 行分开,而不是复制所有代码。

标签: java html jakarta-ee servlets video


【解决方案1】:

老实说,这种做法绝对不对。

  • 您正在嗅探服务器端的用户代理并依赖于它的业务工作。这在所有情况下都是一个坏主意。如果您只想根据用户代理指定不同的文件,那么最好在 HTML 端使用 JavaScript 或 CSS 来完成。两种客户端语言都能够识别真正的浏览器,而无需嗅探用户代理字符串(即可欺骗)。

  • 您没有正确响应 Range 请求。您发送的是完整的文件,而不是请求的 Range。 Firefox 和 IE 不使用范围请求,这就是它“有效”的原因。 Chrome 和 Safari 使用范围请求。

这应该是可能的,无需嗅探用户代理并正确响应RandomAccessFile 而不是Filebyte[]Range 请求。考虑到所有HTTP specification 的要求只需要相当多的代码,所以这里只是一个链接,您可以在其中找到此类 servlet 的具体示例:FileServlet supporting resume and caching

但是,最好将作业委托给 servletcontainer 的默认 servlet。如果是例如 Tomcat,那么您需要做的就是将以下行添加到 /conf/server.xml:

<Context docBase="D:\media" path="/media" />

这样,http://localhost:8080/media/final.ogghttp://localhost:8080/media/final.mp4 就可以使用所需的媒体文件,而无需自行开发 servlet。

【讨论】:

  • 谢谢,这对我很有帮助“FileServlet 支持恢复和缓存”。
  • 对于 tomcat 上下文方法:有没有办法实现对媒体文件的请求过滤器?
【解决方案2】:

这似乎更多是格式支持问题。

你可以试试ogg格式。 HTML5 代码是

<audio controls="controls">
  <source src="song.ogg" type="audio/ogg" />
  Your browser does not support the audio tag.
</audio>

【讨论】:

    【解决方案3】:

    Google Chrome 不支持 H.264(包括 mp4),因此您还需要将 final.ogg 与 google chrome 一起使用。而对于 Safari,您需要更改此行

    browser.indexOf("CoreMedia") != -1
    

    添加“Safari”而不是“CoreMedia”

    我希望它有效。

    【讨论】:

      【解决方案4】:
      String diskfilename = "final.mp4";
      response.setHeader("Content-Disposition", "attachment; filename=\"" + diskfilename + "\"" );
      

      只需评论这两行,然后在 chrome 上运行您的视频即可播放。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多