WebSocket发送文字图片功能

来源:互联网 发布:单片机地址寄存器 编辑:程序博客网 时间:2024/06/05 10:08

  先上效果图: 用户登录以后,就可以像服务端发送文字,或者图片;输入文字的时候,点击发送就可以了,如果发送图片,点击发送图片,选择图片后,会自动发送图片到服务器端;

 

<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Chat Client</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no, user-scalable=no">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="telephone=no" name="format-detection">
</head>
<body>
    <div style="text-align:center">用户登录<br><br>

        用户名:<input type="text" id="Im_Name" value="" style="width:200px;"><br><br>

        密&nbsp;码:<input type="text" id="Im_PassWord" value="" style="width:200px;"><br><br>

        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="button" id="login" value="登录">

        <br><br>

        <br><br>

        <br><br>

    </div>
    <div style="text-align:center">

        <input type="text" id="socketAddress" value="ws://172.21.20.108:1984" style="width:200px; display:none">

        &nbsp;&nbsp; &nbsp;发送文字:<textarea  cols="10" style="width:300px;height:200px" id="textField"></textarea><br><br>

        发送图片:

        <img src="" onclick="F_Open_dialog()" />

        <input type="file" id="Imagg_File" style="display:none" />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;
        <br><br>

        <input type="button" id="send" value="发送">

     </div>

        <div id="result">

            <!-- 这里用来显示读取结果 -->

        </div>


        <div id="result1">

            <!-- 这里用来显示读取结果 -->

        </div>

</body>
</html>
  <script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
  <script type="text/javascript" src="js/reconnecting-websocket.js"></script>
  <script type="text/javascript" src="js/offline.js"></script>
  <script src="layer/layer.js"></script>
  <script src="layer/extend/layer.ext.js"></script>

 <script type="text/javascript">

                var Im_Name=document.getElementById("Im_Name");
                var Im_PassWord=document.getElementById("Im_PassWord");


                var textField=document.getElementById("textField");
                var send = document.getElementById("send");
                var login = document.getElementById("login");
                var result=document.getElementById("result");
                var result1 = document.getElementById("result1");

                var socketStatus = false;
                var globalBufferIndex='';
 
                var websocket = null, tick_heartpac;
                var timerID = '';
                var globaldataindex = '';
                var globalBuffer = '';
                var globalBuffer_REVICE = '';
                var Message_data = "";
                var segment = 50 * 1024;


     function F_Open_dialog() {

         document.getElementById("Imagg_File").click();

                }



  function print(text) {

      result1.innerHTML = (new Date).getTime() + ": " + text + result1.innerHTML+"<br>";;


  }


function initSocket(option) {
    //服务器地址
    layer.msg("建立连接中...");
    var locate = window.location;
    var url = option.url ? option.url : "ws://" + locate.hostname + ":" + locate.port + _get_basepath() + "/websocket";
    //回调函数
    var callback = option.callback;
    if (typeof callback !== "function") {

        layer.msg('callback 必须为函数');
        return false;

    }
    //一些对浏览器的兼容已经在插件里面完成
    websocket = null;
    websocket = new ReconnectingWebSocket(url);

    //连接发生错误的回调方法
    websocket.onerror = function () {

        socketStatus = false;
        layer.msg("websocket.error");

    };

    //连接成功建立的回调方法
    websocket.onopen = function (event) {

        Heart(!0);

        //websocket.send("User_Name|zhang")
        socketStatus = true;
        //t1 = setInterval(tanchuang, 3000);

    }

    //接收到消息的回调方法
    websocket.onmessage = function (event) {

        if (event.data != "@heart")

            callback(event.data);

    }

    //连接关闭的回调方法
    websocket.onclose = function () {

        Heart(!1);

        socketStatus = false;
        layer.msg("websocket Server error");

        websocket.close();
        //if (websocket.readyState == 3) websocket.close();
        //setInterval(initSocket(option), 3000);


    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {

        socketStatus = false;
        websocket.close();

    }

    websocket.onerror = function (evnt) {

        socketStatus = false;
        websocket.close();

    };

    return websocket;

}

$(function () {

    var option = {

        url: $("#socketAddress").val(),
        callback: function (msg) {

            console.log(msg);
            //处理业务逻辑
            var msg_data = eval("(" + msg + ")");//转换为json对象
            //$.each(msg_data, function (index, item) {

            //    $("#info").append(

            //        "<div>" + index + ":" + item.name + "</div>" +

            //        "<div>" + index + ":" + item.value + "</div><hr/>");

            //});
            //layer.msg("数据接收成功" + msg_data.Message);
            if (msg_data.Message_Type == "0") {

                print("[onmessage] '" + msg_data.Message + "'\n");

            }

            else if (msg_data.Message_Type == "999") {

                layer.msg("登录成功\n");
    localStorage.setItem("Im_Id", msg_data.Im_PassWord);
            }

    else if (msg_data.Message_Type == "-1") {
               layer.msg("登录失败\n");
            }
   else if (msg_data.Message_Type == "1") {
                unpackagedata(msg_data.Message);
            }

        }


    };


    initSocket(option);
    send.onclick = function () {

        if (localStorage.getItem("Im_Id") == "") {

            layer.msg("您还没有登录!")

            return;

        }

        alert(localStorage.getItem("Im_Id"));

        var Message = textField.value;

        Message_data = "{ 'Send_Id': '" +  localStorage.getItem("Im_Id") + "', 'To_Id': '10067', 'Message_Type': '0', 'Message': '" + Message + "' }";
        "" != Message && (websocket && 1 == websocket.readyState ? (Heart(!0), websocket.send(Message_data), print("[send] '" + Message + "'\n"), $("#textField").val(""), Heart(!0)) : layer.msg("连接已经断开!"))

    };


    login.onclick = function () {

        var Im_Name1 = Im_Name.value;

  var Im_PassWord1 = Im_PassWord.value;

        Message_data = "{ 'Im_Name': '" + Im_Name1 + "', 'Im_PassWord': '" + Im_PassWord1 + "', 'Message_Type': '-1'}";
        "" != Im_Name1 && (websocket && 1 == websocket.readyState ? (Heart(!0), websocket.send(Message_data), Heart(!0)) : layer.msg("连接已经断开!"))

    };

})

 

function Heart(a) {

    a ? tick_heartpac = setInterval(function () {

        websocket.send("@heart")

    },

    3e4) : (clearInterval(tick_heartpac), tick_heartpac = null)

}


     // 用于压缩图片的canvas
    var canvas = document.createElement("canvas");
    var ctx = canvas.getContext('2d');
     //    瓦片canvas
    var tCanvas = document.createElement("canvas");
    var tctx = tCanvas.getContext("2d");
    var maxsize = 100 * 1024;

    var result = document.getElementById("result");
    var input = document.getElementById("Imagg_File");
    if (typeof FileReader === 'undefined') {

        result.innerHTML = "抱歉,你的浏览器不支持 FileReader";
        input.setAttribute('disabled', 'disabled');

    } else {

        input.addEventListener('change', readFile, false);

    }          
               
    function readFile() {

        var file = this.files[0];
       // if (!/image\/\w+/.test(file.type)) {

        //    alert("请确保文件为图像类型");
        //    return false;

       // }
        var reader = new FileReader();

      reader.readAsDataURL(file);
      reader.onload = function() {
        var result = this.result;
   var img = new Image();
         img.src = result;
        //如果图片大小小于100kb,则直接上传
        if (result.length <= maxsize) {
          img = null;
          sendpicdata(this.result);
          return;
        }
        //图片加载完毕之后进行压缩,然后上传
        if (img.complete) {
          callback();
        } else {
          img.onload = callback;
        }
        function callback() {
          var data = compress(img);
          sendpicdata(data);
          img = null;
        }
      };
    
    }


    function sendpicdata(txt) {

        if (timerID == '') {

      globaldataindex='';
            globalBuffer='';
            globalBuffer = packagedata(txt);

            Message_data ="{ 'Send_Id': '" +  localStorage.getItem("Im_Id") + "', 'To_Id': '10067', 'Message_Type': '1', 'Message': '" + globalBuffer[0] + "' }";

 
            websocket.send(Message_data);
 
            //layer.msg(globalBuffer[0]);
            globalBufferIndex = 1;
            timerID = setInterval(sendBufferInterval, 1000);

        }

    }

    function sendBufferInterval() {

        if (globalBufferIndex < (globalBuffer.length)) {
            Message_data = "{ 'Send_Id': '" +  localStorage.getItem("Im_Id") + "', 'To_Id': '10067', 'Message_Type': '1', 'Message': '" + globalBuffer[globalBufferIndex] + "'}";
            websocket.send(Message_data);
            //layer.msg(globalBuffer[globalBufferIndex]);
            globalBufferIndex += 1;

        }
        else {

            clearInterval(timerID);
            timerID = '';

        }

    }


function hexToString(num) {

    var val = "";
    var str = num.toString(16);

    if (str.length < 4) {

        for (var i = 0; i < (4 - str.length) ; i++) {

            val += '0';

        }

    }
    val += str;
    return val;

}

function packagedata(data) {

    var buffer = new Array();
    var length = data.length;

    alert(length);

    if (length > segment) {

        var packagecount = 0;
        var packagefloor = 0;
        packagecount = Math.ceil(length / (segment));
        packagefloor = Math.floor(length / (segment));
        for (var i = 0; i < packagefloor; i++) {

            buffer[i] = '0001';
            buffer[i] += '0000';
            buffer[i] += hexToString(packagecount);
            buffer[i] += hexToString(i + 1);
            buffer[i] += data.substr(segment * i, segment);

        }

        if (packagecount > packagefloor) {

            buffer[packagecount - 1] = '0001';
            buffer[packagecount - 1] += '0000';
            buffer[packagecount - 1] += hexToString(packagecount);
            buffer[packagecount - 1] += hexToString(packagecount);
            buffer[packagecount - 1] += data.substr(segment * (packagecount - 1), length % (segment));

        }

    }
    else {

        buffer[0] = '0001';
        buffer[0] += '0000';
        buffer[0] += '0001';
        buffer[0] += '0001';
        buffer[0] += data;

    }

    return buffer;

}

function unpackagedata(buffer) {

    var data = new Array();

    data[0] = buffer.substr(0, 4);//0001

    data[1] = buffer.substr(4, 4);//0000

    data[2] = buffer.substr(8, 4);//0001

    data[3] = buffer.substr(12, 4);//0001

    data[4] = buffer.substr(16);

    //layer.msg(buffer);

    view(data);

}

function view(data) {

    debugger;

    if (data[2] == data[3]) {

        if (globaldataindex > data[3]) {

            globaldataindex = '';

        }

        else {

            globaldataindex = data[3];

            globalBuffer_REVICE += data[4];
            //layer.msg(globalBuffer_REVICE);

    //alert(globalBuffer_REVICE);
             result1.innerHTML +='<img src="' + globalBuffer_REVICE + '"  width="100" height="100"  alt=""/>';
            globalBuffer_REVICE = '';

            globaldataindex = 'ffffffff';

        }

    }

    else {

        if (globaldataindex == data[3]) {

        }

        else {

       alert(globalBuffer_REVICE);
            globaldataindex = data[3];

            globalBuffer_REVICE += data[4];

        }

    }

}


 //    使用canvas对大图片进行压缩
  function compress(img) {
    var initSize = img.src.length;
    var width = img.width;
    var height = img.height;
    //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
    var ratio;
    if ((ratio = width * height / 4000000) > 1) {
      ratio = Math.sqrt(ratio);
      width /= ratio;
      height /= ratio;
    } else {
      ratio = 1;
    }
    canvas.width = width;
    canvas.height = height;
//        铺底色
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    //如果图片像素大于100万则使用瓦片绘制
    var count;
    if ((count = width * height / 1000000) > 1) {
      count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
//            计算每块瓦片的宽和高
      var nw = ~~(width / count);
      var nh = ~~(height / count);
      tCanvas.width = nw;
      tCanvas.height = nh;
      for (var i = 0; i < count; i++) {
        for (var j = 0; j < count; j++) {
          tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
          ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
        }
      }
    } else {
      ctx.drawImage(img, 0, 0, width, height);
    }
    //进行最小压缩
    var ndata = canvas.toDataURL('image/jpeg', 0.6);
    console.log('压缩前:' + initSize);
    console.log('压缩后:' + ndata.length);
    console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");
    tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
    return ndata;
  }

 

 </script>


图片过分的大的时候需要分段发送;也可以进行图片压缩;图片的分段和压缩借鉴了网上一些js代码,谢谢各位的无偿奉献;

服务端使用mina开发的;两个客户端通过服务端转发就可以聊天了。


如果大家有好的web端设计或者想法,可以联系。