使用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;  
      }  
复制代码


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

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值