顯示具有 HTML5 標籤的文章。 顯示所有文章
顯示具有 HTML5 標籤的文章。 顯示所有文章

2018年2月3日 星期六

「HTML5][Java] Server-Sent Events

Server-Sent Events

W3Schools上的說明:

server-sent event is when a web page automatically gets updates from a server.
This was also possible before, but the web page would have to ask if any updates were available. With server-sent events, the updates come automatically.
Examples: Facebook/Twitter updates, stock price updates, news feeds, sport results, etc.


簡單來說SSE的特點為"One Way Messaging" ,也就是Client端被動接收Server端訊息。

過去HTTP 都是一個單一回合結束,如果要取得新的資料,必須重新發送一次

HTTP Request,而SSE則是可以持續接收Server資訊,無須主動發送Request ,

但Client端無法透過SSE與Server端進行溝通,這是與webSocket不同的地方。

以下有一個範例,利用Java Servlet 透過SSE的方式與Client端JavaScript溝通.

當下按Start Button後,JavaScript會開始接收由Server端傳送過來的SSE資料,並更新

在網頁上。

Client端程式碼
<!DOCTYPE HTML>
<html>
    <head>
        <title>Server-Sent Events Servlet example</title>
        <script>
            function start() {
                var eventSource = new EventSource("Server");
                eventSource.onmessage = function (event) {
                    document.getElementById('myDiv').innerHTML = event.data;
                }
            }
            ;

        </script>
        <style>
            body {
                font-family: sans-serif;
            }
        </style>
    </head>
    <body>

        Time: <span id="myDiv"></span>

        <br><br>
        <button onclick="start()">Start</button>


    </body>
</html>


Server端Servlet程式碼
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author boywhychen
 */
public class Server extends HttpServlet {

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("UTF-8");

        PrintWriter writer = response.getWriter();

        for (int i = 0; i < 20; i++) {

            writer.write("data: " + getTime() + "\n\n");
            writer.flush();

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        writer.close();
    }

    private String getTime() {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        return sdf.format(cal.getTime());
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

}


參考資料來源:

https://gist.github.com/viralpatel/7007662

2015年8月5日 星期三

[HTML5] 無法撥放MP4

今天在將.MTS 轉換成.Mp4,用chrome在HTML5的網頁撥放,

但卻一片黑畫面,只有聲音。

後來查資料發現,mp4有3種編碼:Xvid\DivX\AVC(H.264)

我是用格式工廠轉的,編碼選擇用Xvid,是無法在瀏覽器上撥放的。



































必須改用H.264才會正常,但檔案大小也會比用Xvid肥大一圈。


































目前測試使用H.264編碼的mp4,在Chrome, FireFox, IE 10 , Edge

4種browser上是可以正常即時撥放的。


參考資料:
http://www.pchou.info/web/2014/01/30/52ea01e13a7f1.html



2015年1月9日 星期五

[HTML5] WebSocket 筆記 (2) - 實做echo server - Java with GlassFish.

在上一篇[HTML5] WebSocket 筆記 (1) -在網頁中使用websocket後,去爬了一下文要怎麼快速建立

一個像Echo Server一樣的功能,查到一個用Web Applaction實做。


環境如下


Web Application  
GlassFish 4.1
SDK                    
JDK 8
IDE                        
Netbean 8.0.1




WebSocket Server Code  (EchoServer.java)

 import java.io.IOException;  
 import java.util.Collections;  
 import java.util.HashSet;  
 import java.util.Set;  
 import javax.websocket.OnClose;  
 import javax.websocket.OnError;  
 import javax.websocket.OnMessage;  
 import javax.websocket.OnOpen;  
 import javax.websocket.Session;  
 import javax.websocket.server.ServerEndpoint;  
 @ServerEndpoint("/echo")  
 public class EchoServer {  
   @OnOpen  
   public void onOpen(Session session) {  
     session.setMaxBinaryMessageBufferSize(1024 * 512);  
     System.out.println(session.getId()+" open");  
   }    
   @OnClose  
   public void onClose(Session session) {  
     System.out.println(session.getId()+" close");  
   }  
   @OnMessage  
   public void onMessage(Session session, String message) throws IOException {  
     session.getBasicRemote().sendText(message);  
     System.out.println(session.getId()+" message: "+message);  
   }  
   @OnError  
   public void onError(Throwable t) {  
     t.printStackTrace();  
   }  
 }  



Web Socect Client  (echoTest.html)

 <!DOCTYPE html>  
 <html>  
   <head>  
     <title>WebSocket Echo Test</title>  
     <meta charset="UTF-8">  
     <meta name="viewport" content="width=device-width, initial-scale=1.0">  
     <script language="javascript" type="text/javascript">  
       //echo server的網址  
       var wsUri = "ws://localhost:8080/DemoEchoServer/echo";  
       //定義元件  
       var outputElement;  
       //初始化function   
       function init()  
       {  
         outputElement = document.getElementById("output");  
         testWebSocket();  
       }  
       //執行websocket測試  
       function testWebSocket() {  
         //連線到echo server  
         websocket = new WebSocket(wsUri);  
         //連線成功要執行的function  
         websocket.onopen = function (evt) {  
           onOpen(evt)  
         };  
         //連結結速要執行的function  
         websocket.onclose = function (evt) {  
           onClose(evt)  
         };  
         //收到echo server傳來的訊息要做的function  
         websocket.onmessage = function (evt) {  
           onMessage(evt)  
         };  
         //當發生錯誤時要執行的function  
         websocket.onerror = function (evt) {  
           onError(evt)  
         };  
       }  
       //連線成功後,在outputElement顯示 ,並傳送一個測試訊息  
       function onOpen(evt) {  
         writeToScreen("連線成功");  
         doSend("hello blogger");  
       }  
       //當中斷連線時輸出訊息在outputElement上        
       function onClose(evt) {  
         writeToScreen("中斷連線");  
       }  
       //收到訊息時顯示在螢幕上  
       function onMessage(evt) {  
         writeToScreen('<span style="color: blue;">接收到: ' + evt.data + '</span>');  
         websocket.close();  
       }  
       //發生錯誤時顯示訊息在outputElement上  
       function onError(evt) {  
         writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);  
       }  
       //發送訊息  
       function doSend(message) {  
         writeToScreen("己傳送 " + message);  
         websocket.send(message);  
       }  
       //輸出訊息在outputElement上  
       function writeToScreen(message) {  
         var pre = document.createElement("p");  
         pre.style.wordWrap = "break-word";  
         pre.innerHTML = message;  
         output.appendChild(pre);  
       }  
       //加入事件,當載入完成後執行init()  
       window.addEventListener("load", init, false);  
     </script>  
   </head>  
   <body>  
     <div id="output"></div>  
   </body>  
 </html>  


執行結果 - Client


















執行結果 -Server




參考資料

https://tyrus.java.net/documentation/1.9/index/websocket-api.html#d0e645

http://javawebsocketsvideo.blogspot.tw/

2015年1月7日 星期三

[HTML5] WebSocket 筆記 (1) -在網頁中使用websocket

WebSocket

WebSocketHTML5開始提供的一種在單個 TCP 連線上進行全雙工通訊的協定。WebSocket通訊協定於2011年被IETF定為標準RFC 6455WebSocketAPIW3C定為標準。
在WebSocket API中,瀏覽器和伺服器只需要做一個握手的動作,然後,瀏覽器和伺服器之間就形成了一條快速通道。兩者之間就直接可以資料互相傳送。

 WebSocket協議定義了WS://和WSS://前綴來表示的WebSocket和WebSocket的安全連接。

資料來源- 維基百科


WebSocket 用起來很簡單,主要只有4個function,這四個function是選擇性的 ,並非全都要用

onopen()

當與server連線成功後會觸發的事件。

onclose()

當結束連線後會觸發的事件 。

onmessage()

收到Server傳送來的訊息時。

onerror()

發生錯誤時會觸發的事件。

以上四個都是事件觸發型的function , 不必用while 來輪詢 ,

有事件發生時自然就會執行這些函式。




以下用一個很簡單的例子來做WebSocket的Client端 與WebSocket Echo Server

做一個連線並發送訊息,Echo Server會回傳我們送給它的訊息。















想了解關於Echo Server,請點這裡  , 程式碼來源請點此 ,我加了一些註解幫助記憶。



 <!DOCTYPE html>  
 <html>  
   <head>  
     <title>WebSocket Echo Test</title>  
     <meta charset="UTF-8">  
     <meta name="viewport" content="width=device-width, initial-scale=1.0">  
     <script language="javascript" type="text/javascript">  
       //echo server的網址  
       var wsUri = "ws://echo.websocket.org/";  
       //定義元件  
       var outputElement;  
       //初始化function   
       function init()  
       {  
         outputElement = document.getElementById("output");  
         testWebSocket();  
       }  
       //執行websocket測試  
       function testWebSocket() {  
         //連線到echo server  
         websocket = new WebSocket(wsUri);  
         //連線成功要執行的function  
         websocket.onopen = function (evt) {  
           onOpen(evt)  
         };  
         //連結結速要執行的function  
         websocket.onclose = function (evt) {  
           onClose(evt)  
         };  
         //收到echo server傳來的訊息要做的function  
         websocket.onmessage = function (evt) {  
           onMessage(evt)  
         };  
         //當發生錯誤時要執行的function  
         websocket.onerror = function (evt) {  
           onError(evt)  
         };  
       }  
       //連線成功後,在outputElement顯示 ,並傳送一個測試訊息  
       function onOpen(evt) {  
         writeToScreen("連線成功");  
         doSend("hello blogger");  
       }  
       //當中斷連線時輸出訊息在outputElement上        
       function onClose(evt) {  
         writeToScreen("中斷連線");  
       }  
       //收到訊息時顯示在螢幕上  
       function onMessage(evt) {  
         writeToScreen('<span style="color: blue;">接收到: ' + evt.data + '</span>');  
         websocket.close();  
       }  
       //發生錯誤時顯示訊息在outputElement上  
       function onError(evt) {  
         writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);  
       }  
       //發送訊息  
       function doSend(message) {  
         writeToScreen("己傳送 " + message);  
         websocket.send(message);  
       }  
       //輸出訊息在outputElement上  
       function writeToScreen(message) {  
         var pre = document.createElement("p");  
         pre.style.wordWrap = "break-word";  
         pre.innerHTML = message;  
         output.appendChild(pre);  
       }  
       //加入事件,當載入完成後執行init()  
       window.addEventListener("load", init, false);  
     </script>  
   </head>  
   <body>  
     <div id="output"></div>  
   </body>  
 </html>  


執行結果


2015年1月3日 星期六

[HTML5] 撥放MP4

前一陣子忽然想起之前去上的HTML5 課程,HTML5 可以撥放影片格式如下 ;











資料來源W3Schools


我們要撥放一個Mp4檔案的話,最直接的方式是在<Body>....</Body> 中放了一個

<video> Element


並指定source 來源。


<video width="480" height="320" controls>
  <source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>


你會看到如下的結果














video element 中的width指的是播放畫面的寬度,height是高度。

假如你的影片是1920 x 1080 , 當指定width及height後,就會將影片

畫面縮放至480 x 320 ,而不是截到某一區塊而以,當然如果你不指定width及height,

影片有多大,撥放區塊就會放到多大。

controls 表示要顯示控制工具列,如果沒有打這個,只會有撥放的區域而以。

結果如下:














Your browser does not support the video tag.
如果您的瀏覽器不支援HTML5 或是video element 則會看到這個。
下圖是IE 6 執行結果。



























今天我要實作一個可以選置檔案來撥放的HTML5網頁,我必須另外實作一個
檔案選擇器,其實也是用一個<input> tag 就可以達成。


 <input type="file" id="files" name="files" accept="video/*"/>  

結果如下圖,會出現一個檔案選擇器 ,不過每一種瀏覽器出現的場子會不太一樣。下面這個是chrome的。






IE 6 會長這樣





I
E 11 長這樣






FireFox 長這個樣子




accept="video/*"/


其實是一種檔案過濾器,只能選擇video 類型的檔案,不加就可以任意選擇所有類型的檔案,但不一定能播放就是了。


當你點下瀏覽(選擇檔案) ,會跳出檔案選擇對話框。





選擇檔案完成後會顯示剛才所選的檔案。






選擇檔的功能到這裡算完成50%了,接下來是當我選擇好檔案後要如果把它指定給video撥放,必須透過javaScript寫一個fucnction來實作這段功能。


  <script type="text/javascript">  
       function handleFileSelect(evt) {  
         var files = evt.target.files; // FileList object  
         var file = files[0];//First File in FileList object  
         var video = document.getElementById('myVideo');  
         var myURL = window.URL || window.webkitURL;          
         var fileURL = myURL.createObjectURL(file);  
         video.src = fileURL;  
       }  


一步步來解釋每一行程式碼。


 var files = evt.target.files;  

當選擇完畢檔案後,取得所選擇的檔案清單。(input可以設定成多選)

  var file = files[0];  

取得所選取的第一個檔案,實際上我們沒有設定多選,所以只能選擇一個檔案。

 var video = document.getElementById('myVideo');   

以video的id 取得video element

 var myURL = window.URL || window.webkitURL    

這行是用來取得URL物件,判定瀏覽器是否要使用prefixed ,chrome必須用window.webkitURL ,firefox則使用window.URL  , 這也寫是為了相容於多種瀏覽器。

 var fileURL = myURL.createObjectURL(file);   

我們要撥放檔案,必須要把它轉換成URL的格式。

 video.src = fileURL;   

指定video 的src (相當於在source 中指定src)。

將input設定一個change事件(選擇的檔案改變後要執行的function)

  function init()  
       {  
         document.getElementById('files').addEventListener('change', handleFileSelect, false);  
       }  

記得在 body 中寫一個事件在網頁載入後去執行init註冊input的change事件。
 onload="init()"  



最後是完整程式碼

 <html>  
   <head>  
     <title>Html5 Mp4</title>  
     <meta charset="UTF-8">  
     <meta name="viewport" content="width=device-width, initial-scale=1.0">  
     <script type="text/javascript">  
       function handleFileSelect(evt) {  
         var files = evt.target.files; // FileList object  
         var file = files[0];//First File in FileList object  
         var video = document.getElementById('myVideo');  
         var myURL = window.URL || window.webkitURL;                       
         var fileURL = myURL.createObjectURL(file);  
         video.src = fileURL;        
       }  
       function init()  
       {  
         document.getElementById('files').addEventListener('change', handleFileSelect, false);  
       }  
     </script>  
   </head>  
   <body onload="init()">  
     <input type="file" id="files" name="files" accept="video/*" />  
     <br>  
     <br>  
     <video id="myVideo" src="" autoplay controls width="480" height="320" >  
       <p>Your browser does not support H.264/MP4.</p>  
     </video>      
   </body>  
 </html>  

執行結果


















當然你也可以按下控制列上的全螢幕鍵享受全螢幕撥放

2014年12月22日 星期一

[HTML5] 用HTML5 開啟WebCam

無意間發現HTML5 可以輕易的開啟Webcam,手癢來Try一下,順手做個筆記。


程式碼來源


首先要加body中加入一個Video Element
  <video id="video" width="640" height="480" autoplay></video>    


在head中新增一個JavaScript ,並新增一個事件監聽

  <script type="text/javascript">  
       // 建立一個監聽事件 (事件名稱 ,要執行的function, useCapture)  
       window.addEventListener("DOMContentLoaded", function () {  
         // Grab elements, create settings, etc.  
         var video = document.getElementById("video"),  
              //使用影像: true ,取用聲音 true  
             videoObj = {video: true ,audio: true},  
         errBack = function (error) {  
           console.log("Video capture error: ", error.code);  
         };  
         // 依據Browser不同使用不同的API          
         if (navigator.getUserMedia) { // Standard  
           navigator.getUserMedia(videoObj, function (stream) {  
             video.src = stream;  
             video.play();  
           }, errBack);  
         } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed  
           navigator.webkitGetUserMedia(videoObj, function (stream) {  
             video.src = window.webkitURL.createObjectURL(stream);  
             video.play();  
           }, errBack);  
         }  
         else if (navigator.mozGetUserMedia) { // Firefox-prefixed  
           navigator.mozGetUserMedia(videoObj, function (stream) {  
             video.src = window.URL.createObjectURL(stream);  
             video.play();  
           }, errBack);  
         }  
         else if (navigator.msGetUserMedia){  
          navigator.msGetUserMedia(videoObj, function (stream) {  
             video.src = window.URL.createObjectURL(stream);  
             video.play();  
           }, errBack);  
         }  
       }, false);  
     </script>  

這裡補充一下onloadDOMContentLoaded 差異: 

當onload事件觸發時,頁面上所有的DOM,樣式表,Script,圖片,flash都已經加載完成了。

當DOMContentLoaded事件觸發時,僅當DOM加載完成,不包括樣式表,圖片,flash。 

我們需要給一些元素(element)的事件綁定處理函數。但問題是,如果那個元素(element)還沒有加載到頁面上,但是綁定事件已經執行完了,是沒有效果的
這時候DOMContentLoaded事件就是一個很好的選擇,當DOMContentLoaded觸發時,所有的元素(element)己加載完成。

 資料來源

http://www.cnblogs.com/hh54188/archive/2013/03/01/2939426.html



接下來說明一下JavaScript整個架構

window.addEventListener 整個函式的架構為

 element.addEventListener(event, function, useCapture);  

event指的事件名稱,在這裡指的是DOMContentLoaded事件。

function 則是發生DOMContentLoaded事件後要執行的事情。

在此則是執行取得WebCam影像以及Mic的動作並顯示在video element中

useCapture則是指是否使用bubbling propagation

此參數是可選擇性的,預設為false

當為false時,為bubbling propagation,  為true時為capturing propagation

這二個的差異可以參考這一篇,寫的挺清楚。


JavaScript 天書 -- 什麼是event bubbling


或是


w3schools 


videoObj = {video: true ,audio: true} 

vide:true 表示取用WebCam , audio :true則表示取用Mic 。

如果這二個值都為true則啟用時如下圖





video: true , audio :false 則如下圖





video: false ,audio: true 則如下圖






  navigator.getUserMedia(videoObj, function (stream) {  
             video.src = stream;  
             video.play();  
           }, errBack);  

getUserMedia() 它提供了存取camera以及麥克風的串流方法。並將取得的串流
當作是video element的資料來源,並啟動video element為播放模式。



完整程式碼如下


 <!DOCTYPE html>  
 <html>  
   <head>   
     <title>Demo HTML5 WebCam</title>  
     <meta charset="UTF-8">  
     <script type="text/javascript">  
       // 建立一個監聽事件 (事件名稱 ,要執行的function, useCapture)  
       window.addEventListener("DOMContentLoaded", function () {  
         // Grab elements, create settings, etc.  
         var video = document.getElementById("video"),  
              //使用影像: true ,取用聲音 true  
             videoObj = {video: true ,audio: true},  
         errBack = function (error) {  
           console.log("Video capture error: ", error.code);  
         };  
         // 依據Browser不同使用不同的API          
         if (navigator.getUserMedia) { // Standard  
           navigator.getUserMedia(videoObj, function (stream) {  
             video.src = stream;  
             video.play();  
           }, errBack);  
         } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed  
           navigator.webkitGetUserMedia(videoObj, function (stream) {  
             video.src = window.webkitURL.createObjectURL(stream);  
             video.play();  
           }, errBack);  
         }  
         else if (navigator.mozGetUserMedia) { // Firefox-prefixed  
           navigator.mozGetUserMedia(videoObj, function (stream) {  
             video.src = window.URL.createObjectURL(stream);  
             video.play();  
           }, errBack);  
         }  
         else if (navigator.msGetUserMedia){  
          navigator.msGetUserMedia(videoObj, function (stream) {  
             video.src = window.URL.createObjectURL(stream);  
             video.play();  
           }, errBack);  
         }  
       }, false);  
     </script>  
   </head>  
   <body>  
     <!-- 放一個Video element 上去 指定大小為640*480 並且自動播放 -->  
     <video id="video" width="640" height="480" autoplay></video>      
   </body>  
 </html>  



*執行時記得允許存取相機/麥克風

 (Chrome)



FireFox





















執行畫面

















瀏覽器支援如下表 ,資料來源