2011-12-21 36 views
5

Mã dưới đây là để phát trực tuyến video. Điều này là tốt với IE9 và firefox nhưng nó không phải là tốt với Chrome và Mac Safari.Video Sử dụng HTML 5 và 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

Một vài lưu ý: những gì bạn đang làm không phải là "phát trực tuyến", bạn chỉ đang phân phối các tệp qua HTTP như bất kỳ phương thức nào khác; xử lý các trình duyệt khác nhau ở cấp độ máy chủ là một ý tưởng rất tồi (và nói chung nó nên được thực hiện càng ít càng tốt); bạn chỉ nên phân tách 2-3 dòng khác nhau cho từng trường hợp thay vì sao chép tất cả mã. – Viruzzo

Trả lời

8

Thành thật mà nói, cách tiếp cận này hoàn toàn không đúng.

  • Bạn đang đánh hơi tác nhân người dùng ở phía máy chủ và tùy thuộc vào công việc kinh doanh trên đó. Đây là trong mọi trường hợp một ý tưởng tồi. Nếu tất cả những gì bạn muốn là chỉ định một tệp khác tùy thuộc vào tác nhân người dùng, thì hãy thực hiện nó ở phía HTML, với sự trợ giúp của JavaScript hoặc CSS. Cả hai ngôn ngữ phía máy khách đều có thể xác định trình duyệt thực mà không cần phải đánh hơi chuỗi tác nhân người dùng (có thể là giả mạo).

  • Bạn không phản hồi chính xác trên Range yêu cầu. Bạn đang gửi lại tệp hoàn chỉnh thay vì yêu cầu Range. Firefox và IE không sử dụng các yêu cầu phạm vi và đó là lý do tại sao nó "hoạt động". Chrome và Safari sử dụng các yêu cầu phạm vi.

này nên có thể không đánh hơi tác nhân người dùng và đáp ứng đúng cách để Range yêu cầu của RandomAccessFile thay vì Filebyte[]. Nó chỉ có khá nhiều mã để đưa tất cả các yêu cầu HTTP specification vào tài khoản, vì vậy đây chỉ là một liên kết nơi bạn có thể tìm thấy một ví dụ cụ thể về một servlet như vậy: FileServlet supporting resume and caching.

Tuy nhiên, tốt hơn hết là giao công việc cho servlet mặc định của servletcontainer. Nếu đó là ví dụ Tomcat, sau đó tất cả các bạn cần làm là thêm dòng sau vào /conf/server.xml:

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

Bằng cách này, các tập tin media mong muốn chỉ có sẵn bằng cách http://localhost:8080/media/final.ogghttp://localhost:8080/media/final.mp4 mà không cần phải homegrow một servlet.

+1

Cảm ơn, điều này rất hữu ích đối với tôi "FileServlet hỗ trợ tiếp tục và lưu vào bộ nhớ đệm". –

+0

Đối với phương pháp tiếp cận ngữ cảnh tomcat: Có cách nào để triển khai bộ lọc yêu cầu cho các tệp phương tiện không? – jwi

0

Google Chrome không hỗ trợ H.264 (bao gồm mp4) nên bạn cũng cần sử dụng final.ogg với google chrome. trong khi cho safari bạn cần thay đổi dòng này

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

thêm "Safari" thay vì "CoreMedia"

tôi hy vọng nó hoạt động.

1

Điều này có vẻ là vấn đề về hỗ trợ định dạng hơn.

Bạn có thể thử định dạng ogg. Mã HTML5 là

<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 + "\""); 

Chỉ cần bình luận hai dòng sau và sau đó chạy trên chrome video của bạn sẽ chơi.

Các vấn đề liên quan