Javascript: Reading only the last x amount of lines of large server text file

本小妞迷上赌 提交于 2019-12-10 21:34:16

问题


today I was working with very large log files and I want to display them via lighttpd on my RPi, but they grow bigger every day and thus soon will take a very long time to load.

To prevent this problem I figured I would be able to have a button to read, say the last 500 lines from this log file. Of course I have not much experience with javascript, but I think it is doable, right?

Anyway, I couldn't find any good tutorial describing how to do this in javascript, although I found this in PHP, but since I'm not working in PHP I cannot use it. So, a example of how to read the last 500 lines in javascript or maybe a button to progressively read 500 lines every time you click on a button starting from the end of the file would be extremely handful for me.

Thanks in advance, guys.

(P.S: I've read it's not possible to read a file with javascript, but with AJAX calls it is possible.)


回答1:


No, it's not possible with JavaScript. The client makes a request for a resource at a uniform resource locator - it's up to your server to serve up the last 500 lines if that's the desired response.

Simple unix command tail -500 mylog can be interpreted by a number of server-side scripting languages if PHP isn't available to you.




回答2:


Strictly speaking, you might be able to do this by making two HTTP requests:

  1. Make a HEAD request, which should return a Content-Length header, which tells you the size of the file.
  2. Do a GET request with a Content-Range header to request the last N bytes of the file.

Of course, this only works if the lines in the file tend to stay close to a particular average length. So if you know the lines in the file tend to have around 100 bytes, and you want the last 20 lines, you could request the last, say, 2,400 bytes (20 lines ✕ 100 bytes + 20% for good measure). Then you could parse the response to get the last 20 lines.

This is untested (since I don't have a server handy to test against) and doesn't have any error handling, but something like this ought to work, assuming lighttpd is configured to return the Content-Range header with responses to HEAD requests:

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

It's kind of convoluted, and requires requesting extra data every time (and if you're getting a lot of data there are memory implications, especially with the naive data.split), and I'm not sure if lighthttp is equipped to do this out of the box, but it's an idea!




回答3:


If you have Ruby handy, here's a quick CGI script that does what's discussed in the comments above:

#!/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)) }

And here's a lighttpd configuration (not mine) that shows how to point lighttpd at the script.



来源:https://stackoverflow.com/questions/24493783/javascript-reading-only-the-last-x-amount-of-lines-of-large-server-text-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!