在web上逐行輸出較大的txt檔案

桃子夭夭發表於2014-06-30

在某些場景下,需要在web上展示一些日誌檔案,這些日誌檔案是放在檔案伺服器上的一些txt。

當日志檔案很大時,下載日誌會導致頁面長時間卡住,一直在loading狀態,而且下載完日誌之後分析日誌並生成dom,瞬間大量的dom渲染可能導致頁面崩潰。

於是想著優化一下日誌的輸出方式,開始下載即在頁面上一行一行列印日誌,就像一些IDE中輸出程式的編譯過程一樣。

最終實現的方法如下:

在下載檔案的時候,讓請求過一層代理,代理寫輸出流的時候分段輸出:

int l;
        byte[] buffer = new byte[100];
        string llength = "";
        int lsum = 0;
        do
        {
            l = proxyResponseStream.Read(buffer, 0, buffer.Length);
            llength += "," + l;
            lsum += l;
            if (l > 0)
            {
                context.Response.Write(System.Text.Encoding.UTF8.GetString(buffer, 0, l));
                context.Response.Flush();
            }
        }
        while (l > 0);
        context.Response.End();

客戶端請求:

 

 

var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function (e) {
                if (this.readyState == 3) {
                    //alert(1);
                    var newload = e.target.responseText.slice(logs[type].length);
                    var newloadLogs = newload.split('\n');
                    newloadLogs.forEach(function (line, index) {
                        if (index == newloadLogs.length - 1) return;
                        logs[type] += line + '\n';
                        $("#" + type).append("<p class='logline " + getLogType(line) + "'>" + line + "</p>");
                        document.body.scrollTop = document.body.scrollHeight;
                    });
                }
            };
            xhr.onload = function () {
                if (callback) callback();
            }
            xhr.send();
onreadystatechange

response多次輸出值時,readystate一直是3,onreadystatechange事件可以被多次觸發,。

這樣確實可以實現上面所說,無需等待直接開始逐行列印日誌。

 

但是在實現的過程中發現了這樣一些問題

1.response物件在向客戶端寫輸出流的時候,自己也是有設定一個類似buffer的東西的,只不過這個buffer尺寸很大,對於一般的txt,就算捕獲了readystatechange事件,也感覺不出來是在分段輸出。當buffer的尺寸被手動設小,滿了直接flush的時候,就可以看到日誌一小段一小段的列印出來了。不幸的是,這樣會大大降低檔案被下載的速度,並且佔用大量系統資源,失去了優化日誌展現的初衷。

2.response在一段一段輸出檔案內容的時候,在readystatechange事件中並不能獲得每一段輸出的值,而是把新輸出的內容不斷往已輸出內容後邊append。這樣要一段一段解析dom,就需要不斷的去記錄位置、擷取字串,這樣對瀏覽器來說是一個巨大的消耗。

3.我拿一個30M大小的txt在本機上測試,開始輸出日誌後CPU佔用瞬間到90%,輸出大約一半後瀏覽器崩潰...

 

所以最終得出的結論是:這種方式只能作為日誌檔案不大的情況下,對互動體驗的一種優化,且需要消耗大量系統資源。瀏覽器中不適合直接展示比較大的txt,它長時間的下載等待以及對瀏覽器造成的巨大壓力是無法優化的,要麼分段檢視,要麼下載後檢視或者對其作分析後展現結果。

相關文章