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">
            <input type="file" id="file" /><br />
            <input type="button" value
="中止" onclick="stop();" />&empty; <input type="button" value="繼續" onclick="containue();" /> <progress id="progressOne" style="width:400px;" max="100" value="0"></progress> <blockquote id="Status" style="word-break:break-all;"></blockquote>
</div> </div> </div>
複製程式碼

JS:

複製程式碼
/*
    * 測試WebSocket上傳
    * 本地瀏覽器上傳速度測試單個檔案,上傳速度IE>FF>Google(Google瀏覽器慢相當多)
    */
var fileBox = document.getElementById('file');
var reader = null;  //讀取操作物件
var step = 1024 * 256;  //每次讀取檔案大小 ,位元組數
var cuLoaded = 0; //當前已經讀取總數
var file = null; //當前讀取的檔案物件 var enableRead = true;//標識是否可以讀取檔案 var total = 0; //記錄當前檔案總位元組數 var startTime = null; //標識開始上傳時間 fileBox.onchange = function () { //獲取檔案物件 file = this.files[0]; total = file.size; console.info("檔案大小:" + file.size); if (ws == null) { if (window.confirm('建立與伺服器連結失敗,確定重試連結嗎')) { createSocket(function () { bindReader(); }); } return; } bindReader(); } //繫結reader function bindReader() { cuLoaded = 0; startTime = new Date(); enableRead = true; reader = new FileReader(); //讀取一段成功 reader.onload = function (e) { console.info('讀取總數:' + e.loaded); if (enableRead == false) return false; //根據當前緩衝區來控制客戶端讀取速度 if (ws.bufferedAmount > step * 10) { setTimeout(function () { //繼續讀取 console.log('--------------》進入等待'); loadSuccess(e.loaded); }, 3); } else { //繼續讀取 loadSuccess(e.loaded); } } //開始讀取 readBlob(); } //讀取檔案成功處理 function loadSuccess(loaded) { //將分段資料上傳到伺服器 var blob = reader.result; //使用WebSocket 伺服器傳送資料 if (cuLoaded == 0) //傳送檔名 ws.send(file.name); ws.send(blob); //如果沒有讀完,繼續 cuLoaded += loaded; if (cuLoaded < total) { readBlob(); } else { console.log('總共上傳:' + cuLoaded + ',總共用時:' + (new Date().getTime() - startTime.getTime()) / 1000); } //顯示結果進度 var percent = (cuLoaded / total) * 100; document.getElementById('Status').innerText = percent; document.getElementById('progressOne').value = percent; } //指定開始位置,分塊讀取檔案 function readBlob() { //指定開始位置和結束位置讀取檔案 var blob = file.slice(cuLoaded, cuLoaded + step); reader.readAsArrayBuffer(blob); } //中止 function stop() { //中止讀取操作 console.info('中止,cuLoaded:' + cuLoaded); enableRead = false; reader.abort(); } //繼續 function containue() { console.info('繼續,cuLoaded:' + cuLoaded); enableRead = true; readBlob(); } var ws = null; //建立和伺服器的WebSocket 連結 function createSocket(onSuccess) { var url = 'ws://localhost:55373/ashx/upload3.ashx'; ws = new WebSocket(url); ws.onopen = function () { console.log('connected成功'); if (onSuccess) onSuccess(); } ws.onmessage = function (e) { var data = e.data; if (isNaN(data) == false) { //console.log('當前上傳成功:' + data); } else { console.info(data); } } ws.onclose = function (e) { //中止客戶端讀取 stop(); console.log('連結斷開'); } ws.onerror = function (e) { //中止客戶端讀取 stop(); console.info(e); console.log('傳輸中發生異常'); } } //頁面載入完建立連結 createSocket();
複製程式碼
伺服器後臺處理:
複製程式碼
    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 = "";
        //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);
                //判斷使用者傳入的型別進行處理
                if (result.MessageType == WebSocketMessageType.Text)
                {
                    string msg = Encoding.UTF8.GetString(buffer.Array, 0, curLength);
                    filename = msg;
                    buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes("接收檔名成功:" + filename));
                    await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
                }
                else if (result.MessageType == WebSocketMessageType.Binary)
                {
                    //建立並儲存檔案,如果上傳成功,返回當前接收到的檔案大小
                    string msg = SaveFile(filename, buffer, curLength);
                    buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(curLength.ToString()));
                    await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
                }
            }
            else { break; }
        }
    }
    /// <summary>
    /// 追加二進位制資料到檔案
    /// </summary>
    public string SaveFile(string file, ArraySegment<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);
            }
            finally
            {
                fs.Close();
            }
            return "儲存檔案成功";
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
    }
複製程式碼