2014-06-30 29 views
3

今天我正在處理非常大的日誌文件,我想通過我的RPi上的lighttpd顯示它們,但它們每天都會變大,因此很快加載的時間很長。Javascript:僅讀取大型服務器文本文件的最後x行數量

爲了防止這個問題,我想我可以有一個按鈕來讀取,說這個日誌文件的最後500行。當然,我沒有太多的JavaScript經驗,但我認爲這是可行的,對吧?

無論如何,我找不到任何好的教程描述如何在JavaScript中做到這一點,雖然我在PHP中發現this,但由於我不在PHP中工作,我無法使用它。因此,如何在javascript中讀取最後500行或者每次單擊文件末尾的按鈕時逐漸讀取500行的按鈕的例子對我來說都是非常少用的。

在此先感謝,夥計們。

P.S:我讀過它無法讀取使用JavaScript文件,但AJAX調用是可以的。)

+0

我不認爲這是可能的。爲什麼你不能使用PHP?當您向服務器請求(請求)文件時,服務器必須最終發送整個文件。 – soktinpk

+0

@soktinpk它使得我的RPi擁有更多的配置,我想盡可能簡單地保持它,如果這是不可能的,我可能不得不去用PHP。 – Linus

+0

我可以想到的唯一方法是,那麼就是手動將大文件分割成500行單獨的塊。 – soktinpk

回答

4

不,這是不可能的JavaScript。客戶端在統一資源定位器中請求資源 - 如果這是所需的響應,則服務器要爲最後500行服務。

簡單的unix命令tail -500 mylog可以通過許多服務器端腳本語言來解釋,如果PHP不適用於您。

+0

感謝您的建議,似乎需要多餘的配置可能無論如何值得PHP來工作,我將如何輕鬆調用PHP的unix命令? – Linus

+0

當然,http://stackoverflow.com/a/5848101/353802 – AlienWebguy

2

嚴格地說,你可能能夠通過使兩個HTTP請求,要做到這一點:

  1. 做一個HEAD請求,這應該返回Content-Length頭,它告訴你的文件的大小。
  2. 做一個GET請求與Content-Range標題請求最後N字節的文件。

當然,這隻有在文件中的行傾向於保持接近特定平均長度時纔有效。因此,如果您知道文件中的行傾向於有大約100個字節,並且您希望最後20行,則可以請求最後一個例如2400個字節(20行✕100字節+ 20%,以獲得較好的效果)。然後,您可以解析響應以獲取最後20行。

這是未經測試的(因爲我沒有一個方便測試的服務器)並且沒有任何錯誤處理,但是像這樣的東西應該能夠工作,假設lighttpd被配置爲返回Content-Range頭部, HEAD請求:

var url = "http://example.com/some-file.txt", 
    averageLineLength = 100, 
    numLinesToFetch = 20, 
    marginForError = 0.2, 
    bytesToFetch  = averageLineLength * numLinesToFetch * (1 + marginForError) 
; 

$.ajax({ url: url, type: "HEAD" }) 
    .then(function(_, _, xhr) { 
    var fileSize = parseInt(xhr.getResponseHeader('Content-Length')), 
     contentRangeStart = fileSize - bytesToFetch, 
     contentRangeEnd = fileSize - 1, 
     contentRange  = contentRangeStart + "-" + contentRangeEnd + "/" + fileSize, 
     headers   = { "Content-Length": bytesToFetch, 
           "Content-Range": "bytes " + contentRange } 
    ; 

    return $.ajax({ url: url, type: "GET", headers: headers }); 
    }) 
    .then(function(data, statusText, xhr) { 
    var lines = data.split("\n"); 
    lines = lines.slice(numLinesToFetch * -1); 
    console.log("Last " + numLinesToFetch + " lines:\n", 
       lines); 
    }) 
; 

這是一種令人費解,並要求每次請求額外的數據(如果你得到大量的數據有記憶的影響,特別是與天真data.split),我不當然,如果lighthttp裝備好了,可以開箱即用,但這是一個主意!

+0

謝謝你的建議,但它可能需要更多的時間來實現類似的東西,然後它會設置PHP的lighttpd和配置等。 – Linus

+0

@Linus這是可以理解的,儘管編寫示例代碼確實很有趣。 –

0

如果你有紅寶石得心應手,這裏有一個快速的CGI腳本,做什麼在上述意見討論:

#!/usr/bin/env ruby 
require "cgi" 

NUM_LINES = 20 
FILE_TO_TAIL = "/var/log/system.log" 
COMMAND  = "| tail -#{NUM_LINES} #{FILE_TO_TAIL}" 

cgi = CGI.new 
open(COMMAND) {|io| cgi.out("text/plain", &io.method(:read)) } 

而這裏的a lighttpd configuration(不是我)展示瞭如何在腳本點lighttpd的。