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

 


本地瀏覽器上傳速度測試單個文件,上傳速度IE>FF>Google(Google瀏覽器慢相當多)
原因:每次send發送數據的時候Google瀏覽器發送的數據量相對較小

分段上傳文件(六): 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