1. 程式人生 > >HTML5 檔案域+FileReader 分段讀取檔案並上傳(八)-WebSocket

HTML5 檔案域+FileReader 分段讀取檔案並上傳(八)-WebSocket

一、同時上傳多個檔案處理

HTML:

複製程式碼
<div class="container">
    <div class="panel panel-default">
        <div class="panel-heading">分段讀取檔案:</div>
        <div class="panel-body" id="bodyOne">
            <input type="file" id="file"  multiple/><br />
        </
div> </div> </div>
複製程式碼

JS:

1.封裝單文上傳例項

複製程式碼
//封裝 單個檔案上傳例項
(function () {
    var url = 'ws://localhost:55373/ashx/upload4.ashx';
    //指定上傳檔案,建立上傳操作物件
    function uploadOperate(file) {
        var _this = this;
        this.reader = new FileReader();//
讀取檔案物件 this.step = 1024 * 256;//每次讀取檔案位元組數 this.curLoaded = 0; //當前讀取位置 this.file = file; //當前檔案物件 this.enableRead = true; //指定是否可讀取, this.total = file.size; //當前檔案總大小 this.startTime = new Date(); //開始讀取時間 //建立顯示 this.createItem(); this.initWebSocket(function
() { _this.bindReader(); }); console.info('檔案大小:' + this.total); } uploadOperate.prototype = { //繫結讀取事件 bindReader: function () { var _this = this; var reader = this.reader; var ws = this.ws; reader.onload = function (e) { //判斷是否能再次讀取 if (_this.enableRead == false) return; //根據當前緩衝區 控制讀取速度 if (ws.bufferedAmount >= _this.step * 20) { setTimeout(function () { _this.loadSuccess(e.loaded); }, 5); console.info('---->進入等待'); } else { _this.loadSuccess(e.loaded); } } //開始讀取 _this.readBlob(); }, //讀取成功,操作處理 loadSuccess: function (loaded) { var _this = this; var ws = _this.ws; //使用WebSocket 將二進位制輸出上傳到伺服器 var blob = _this.reader.result; if (_this.curLoaded <= 0) ws.send(_this.file.name); ws.send(blob); //當前傳送完成,繼續讀取 _this.curLoaded += loaded; if (_this.curLoaded < _this.total) { _this.readBlob(); } else { //傳送讀取完成 ws.send('傳送完成'); //讀取完成 console.log('總共上傳:' + _this.curLoaded + ',總共用時:' + (new Date().getTime() - _this.startTime.getTime()) / 1000); } //顯示進度等 _this.showProgress(); }, //建立顯示項 createItem: function () { var _this = this; var blockquote = document.createElement('blockquote'); var abort = document.createElement('input'); abort.type = 'button'; abort.value = '中止'; abort.onclick = function () { _this.stop(); }; blockquote.appendChild(abort); var containue = document.createElement('input'); containue.type = 'button'; containue.value = '繼續'; containue.onclick = function () { _this.containue(); }; blockquote.appendChild(containue); var progress = document.createElement('progress'); progress.style.width = '400px'; progress.max = 100; progress.value = 0; blockquote.appendChild(progress); _this.progressBox = progress; var status = document.createElement('p'); status.id = 'Status'; blockquote.appendChild(status); _this.statusBox = status; document.getElementById('bodyOne').appendChild(blockquote); }, //顯示進度 showProgress: function () { var _this = this; var percent = (_this.curLoaded / _this.total) * 100; _this.progressBox.value = percent; _this.statusBox.innerHTML = percent; }, //執行讀取檔案 readBlob: function () { var blob = this.file.slice(this.curLoaded, this.curLoaded + this.step); this.reader.readAsArrayBuffer(blob); }, //中止讀取 stop: function () { this.enableRead = false; this.reader.abort(); console.log('讀取中止,curLoaded:' + this.curLoaded); }, //繼續讀取 containue: function () { this.enableRead = true; this.readBlob(); console.log('讀取繼續,curLoaded:' + this.curLoaded); }, //初始化 繫結建立連線 initWebSocket: function (onSuccess) { var _this = this; var ws = this.ws = new WebSocket(url); //初始化上傳物件 ws.onopen = function () { console.log('connect建立成功'); if (onSuccess) onSuccess(); } ws.onmessage = function (e) { var data = e.data; if (isNaN(data) == false) { console.info('後臺接收成功:' + data); } else { console.info(data); } } ws.onclose = function (e) { //中止讀取 _this.stop(); console.log('connect已經斷開'); } ws.onerror = function (e) { //中止讀取 _this.stop(); console.log('發生異常:' + e.message); } } }; window.uploadOperate = uploadOperate; })();
複製程式碼

2.繫結頁面處理

複製程式碼
/*
* 測試WebSocket多檔案上傳
* 上傳速度取決於 每次send() 的資料大小 ,Google之所以相對比較慢,是因為每次send的資料量太小
*/
var fileBox = document.getElementById('file');
fileBox.onchange = function () {
    var files = this.files;
    for (var i = 0; i < files.length; i++) {
        var file = files[i];
        var operate = new uploadOperate(file);
    }
}
複製程式碼

伺服器後臺封裝處理:

複製程式碼
    public void ProcessRequest(HttpContext context)
    {
        //處理WebSocket 請求
        context.AcceptWebSocketRequest(DoWork);
    }
    /// <summary>
    /// 委託處理函式定義
    /// </summary>
    /// <param name="context">當前WebSocket上下文</param>
    /// <returns></returns>
    public async Task DoWork(AspNetWebSocketContext context)
    {
        //1.獲取當前WebSocket 物件
        WebSocket socket = context.WebSocket;
        string filename = "";
        byte[] bufferAll = new byte[1024 * 256 * 2];//快取接收檔案

        //Array.Copy
        //byte[] bufferAll = new byte[];
        int loaded = 0;  //當前緩衝數量
        //2.監視相應
        while (true)
        {
            /*
                * 此處快取陣列指定讀取客戶端資料的長度
                * 如果客戶端傳送資料超過當前快取區,則會讀取多次
                */
            ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024 * 256]);
            //接收客戶端資訊
            CancellationToken token;
            WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, token);
            if (socket.State == WebSocketState.Open)
            {
                //判斷是否已經到了最後
                int curLength = Math.Min(buffer.Array.Length, result.Count);
                try
                {
                    //判斷使用者傳入的型別進行處理
                    if (result.MessageType == WebSocketMessageType.Text)
                    {
                        string msg = Encoding.UTF8.GetString(buffer.Array, 0, curLength);
                        if (msg == "傳送完成")
                        {
                            //傳送完成,全部寫入檔案
                            string str = SaveFile(filename, bufferAll, loaded);
                            loaded = 0;
                            ArraySegment<byte> echor = new ArraySegment<byte>(Encoding.UTF8.GetBytes(curLength.ToString()));
                            await socket.SendAsync(echor, WebSocketMessageType.Text, true, CancellationToken.None);
                        }
                        else
                        {
                            filename = msg;
                            msg = string.Format("伺服器連結數量:{0},當前連結ID={1},接收檔名:{2}",
                            AspNetWebSocketContext.ConnectionCount, context.AnonymousID, filename);
                            ArraySegment<byte>  echor = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msg));
                            await socket.SendAsync(echor, WebSocketMessageType.Text, true, CancellationToken.None);
                        }
                    }
                    else if (result.MessageType == WebSocketMessageType.Binary)
                    {
                        var temp = loaded + curLength;
                        if ((temp) > bufferAll.Length)
                        {
                            //先寫入檔案
                            string msg = SaveFile(filename, bufferAll, loaded);
                            //新增到緩衝區
                            Array.Copy(buffer.Array, 0, bufferAll, 0, curLength);
                            loaded = curLength;
                            //返回相應
                            ArraySegment<byte> echor = new ArraySegment<byte>(Encoding.UTF8.GetBytes(curLength.ToString()));
                            await socket.SendAsync(echor, WebSocketMessageType.Text, true, CancellationToken.None);
                        }
                        else
                        {
                            //新增到緩衝區
                            Array.Copy(buffer.Array, 0, bufferAll, loaded, curLength);
                            loaded = temp;
                        }
                    }
                }
                catch (Exception ex)
                {

                       
                }
            }
            else { break; }
        }
    }
    /// <summary>
    /// 追加二進位制資料到檔案
    /// </summary>
    public string SaveFile(string file, byte[] buffer, int Length)
    {
        //去除檔名中的前後空格
        file = file.Trim();
        string fullname = @"F:\JavaScript_Solution\H5Solition\UploadWebForm\content\" + file;
        try
        {
            FileStream fs = new FileStream(fullname, FileMode.Append, FileAccess.Write);
            try
            {
                //byte[] result = buffer.ToArray();
                //fs.Write(result, 0, Length);
                fs.Write(buffer, 0, Length);
            }
            finally
            {
                fs.Close();
            }
            return "儲存檔案成功";
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
    }
複製程式碼

執行結果顯示:


更多Demo原始碼:

http://git.oschina.net/tiama3798/HTML5Demo/tree/WebSocket/

http://git.oschina.net/tiama3798/HTML5Demo/tree/FileReader/