2011-12-21 94 views
5

下面給出的代碼是用於視頻流。這對IE9和Firefox來說很好,但Chrome和Mac Safari並不好。視頻使用HTML 5和servlet

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; 
    } 

} 
+0

一些注意事項:你在做什麼不是「流媒體」,你只是通過HTTP服務文件作爲任何其他;在服務器級別處理不同的瀏覽器是一個非常糟糕的主意(並且通常應該儘可能少地完成);你應該只分離出2-3個不同的情況,而不是複製所有的代碼。 – Viruzzo 2011-12-21 15:05:29

回答

8

老實說,這種做法絕對不對。

  • 您正在服務器端嗅探用戶代理,並依賴其上的業務作業。這在所有情況下都是一個壞主意。如果你只想根據用戶代理指定一個不同的文件,那麼在JavaScript或CSS的幫助下,可以在HTML端執行。兩種客戶端語言都能夠識別真實瀏覽器,而無需嗅探用戶代理字符串(即可僞造)。

  • 您在Range請求中沒有正確響應。您發送完整的文件而不是請求的Range。 Firefox和IE不使用範圍請求,這就是它「工作」的原因。 Chrome和Safari使用範圍請求。

這應該不嗅探用戶代理,並通過RandomAccessFile代替Filebyte[]正確響應Range請求是可能的。考慮到所有的HTTP specification需求只有很多代碼,所以這裏只是一個鏈接,你可以在這裏找到一個這樣的servlet的具體例子:FileServlet supporting resume and caching

然而,更好的做法是將作業委託給servlet容器的默認servlet。如果是例如Tomcat的,那麼所有你需要做的是以下行添加到/conf/server.xml

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

這種方式所需的媒體文件只是http://localhost:8080/media/final.ogghttp://localhost:8080/media/final.mp4可用而不需要homegrow一個servlet。

+1

謝謝,這對我「FileServlet支持簡歷和緩存」非常有幫助。 – 2011-12-28 12:26:03

+0

對於tomcat上下文方法:是否有一種方法可以實現對媒體文件的請求過濾器? – jwi 2017-09-06 11:39:17

0

Google Chrome不支持H.264(包括mp4),因此您還需要在google chrome中使用final.ogg。而Safari瀏覽器,你需要改變這一行

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

加上「野生動物園」,而不是「CoreMedia」

我希望它的作品。

1

這似乎是更多的格式支持問題。

您可以嘗試ogg格式。 HTML5的代碼是

<audio controls="controls"> 
  <source src="song.ogg" type="audio/ogg" /> 
  Your browser does not support the audio tag. 
</audio> 
0
String diskfilename = "final.mp4"; 
response.setHeader("Content-Disposition", "attachment; filename=\"" + diskfilename + "\""); 

就評論這兩條線,然後對鉻播放視頻運行。