使用Html5的WebSocket在浏览器上传文件, 支持多文件和大文件.

来源:互联网 发布:jsp数据展示样式 编辑:程序博客网 时间:2024/06/11 22:45
使用Html5的WebSocket在浏览器上传文件, 支持多文件和大文件.

使用websocket上传文件的简单例子: 使用Html5的WebSocket在浏览器上传文件

上篇文章没有解决的问题就是大文件的上传问题, 而且多文件上传问题也未协调. 所以这篇文章就是解决这两个问题的.

如果将一个大文件直接读入内存再发送的话, 内存会吃不消, 所以我们把大文件分块传输.  Html5的Fileread方法提供了读取文件部分内容Blob的方法.

为了保证后台接收到的分块数据的顺序不会乱掉, 我们需要后台确定写入分块数据后再发送下一块数据. 

在Html端:

复制代码
<!DOCTYPE html><html><head><title>WebSocket Chat Client</title><meta charset="utf-8" /><script type="text/javascript" src="jquery-1.6.4.min.js"></script><script type="text/javascript" src="jquery.json-2.3.min.js"></script><script type="text/javascript">    $().ready(                    function() {                        // Check for the various File API support.              if (window.File && window.FileReader && window.FileList                                && window.Blob) {                            // Great success! All the File APIs are supported.                        } else {                            alert('The File APIs are not fully supported in this browser.');                        }                    });    //在消息框中打印内容    function log(text) {        $("#log").append(text+"\n");    }    //全局的websocket变量
var ws;    var paragraph = 10485760;    var fileList ;    var file;    var startSize,endSize = 0;    var i = 0; j = 0;    //连接服务器    $(function() {    $("#connect").click(function() {        ws = new WebSocket($("#uri").val());        //连接成功建立后响应        ws.onopen = function() {            log("成功连接到" + $("#uri").val());        }        //收到服务器消息后响应        ws.onmessage = function(e) {            log("服务器说" + e.data + (e.data=="ok"));            if(e.data == "ok"){            if(endSize < file.size){                startSize = endSize;                endSize += paragraph ;                if (file.webkitSlice) {                          var blob = file.webkitSlice(startSize, endSize);                } else if (file.mozSlice) {                          var blob = file.mozSlice(startSize, endSize);                }                var reader = new FileReader();                reader.readAsArrayBuffer(blob);                reader.onload = function loaded(evt) {                    var ArrayBuffer = evt.target.result;                    log("发送文件第" + (i++) + "部分");                    ws.send(ArrayBuffer);                    }            }            else{                    startSize = endSize = 0;                    i = 0;                    log("发送" + file.name +"完毕");                    file = fileList[j++];                    if(file.name){                    ws.send(file.name);                    }                    log("发送文件完毕");            }        }        //连接关闭后响应        ws.onclose = function() {            log("关闭连接");            ws = null;        }        return false;        }    });    });    $(function() {        $("#sendFileForm").click(function() {            fileList = document.getElementById("file").files;            file = fileList[0];            ws.send(file.name);        })    });    $(function() {    $("#reset").click(function() {        $("#log").empty();         return false;    });    });        </script></head><body>    <span>Html5功能测试</span>    <span id="progress">0</span><br>    <input type="text" id="uri" value="ws://localhost:8887"            style="width: 200px;"> <input type="button" id="connect"            value="Connect"><input type="button" id="disconnect"            value="Disconnect" disabled="disabled">    <form >        <input id="file" type="file" multiple />         <input type="button" id="sendFileForm" value="测试" />         <input type="button" id="reset" value="清空消息框" />    </form>    <form>        <textarea id="log" rows="30" cols="100"            style="font-family: monospace; color: red;"></textarea>    </form></body></html>
复制代码

这里设置了文件大于paragraph (10M)时就会分块发送文件.


服务器端:

复制代码
/*** 处理字符串消息*/public void onMessage( WebSocket conn, String message ) {        System.out.println("文件名" + message);        //将文件名写入连接对象中,(需要手动修改webSocket类)        conn.setFileName(message);        try {            conn.send("ok");        } catch (NotYetConnectedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IllegalArgumentException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }
复制代码
复制代码
/*** 处理二进制消息*/    public void onMessage(WebSocket conn, byte[] message) {        System.out.println("收到二进制流:");        //将二进制流保存为文件, 文件名从连接对象中取出        saveFileFromBytes(message, "src/" + conn.getFileName());        //告诉前台可以继续发送了.        try {                conn.send("ok");        } catch (NotYetConnectedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IllegalArgumentException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }     /**     * 将二进制byte[]数组写入文件中     * @param b byte[]数组     * @param outputFile 文件位置     * @return 成功: true 失败: false     */        public static boolean saveFileFromBytes(byte[] b, String outputFile)        {          FileOutputStream fstream = null;          File file = null;          try          {            file = new File(outputFile);            fstream = new FileOutputStream(file, true);            fstream.write(b);        }          catch (Exception e)          {            e.printStackTrace();          return false;        }          finally          {            if (fstream != null)            {              try              {                  fstream.close();              }              catch (IOException e1)              {                e1.printStackTrace();              }            }          }          return true;        }  
复制代码


好了, 顺序发送保证了后台写入的数据也是顺序的, 文件就不会出错了! 搞定!

原创粉丝点击