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;
})();
View Code

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;
        }
    }
View Code

運行結果顯示:

分段上傳文件(七):http://www.cnblogs.com/tianma3798/p/5852475.html

分段上傳文件(六): http://www.cnblogs.com/tianma3798/p/5845291.html
分段讀取文件(五): http://www.cnblogs.com/tianma3798/p/5841584.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM