Reading local file in javascript [duplicate]

2019-09-25 04:42发布

This question already has an answer here:

Is there a way to, in JavaScript running in the client's browser, access a local file for IO in following manner? The file is being appended to regularly (every ~25ms). We want to read every new line as it comes in. Preferably asynchronously (we get some kind of signal, or a callback executes) when anything is appended. Is this possible? If so, how?

My experience with Javascript is limited to D3, so a basic explanation on how or why/why not this is feasible would be appreciated. I can totally understand this not being possible due to security reasons.

EDIT: Just to make it clear, the file is on the clients computer. The file is just a text file. The process appending to it is a native process on the client's machine.

1条回答
趁早两清
2楼-- · 2019-09-25 05:43

The answer is not really, no.

BUT there are some workarounds, depending on what you can get away with (supported browsers, etc)

When you grab a local file (I'm assuming you're using <input type="file">, rather than partially supported, unstandardized methods), you get a "change" event to subscribe to, but that change reflects the change in selected files, not a change in the contents of a particular file.

Moving beyond that, if you have a Blob or a File which inherits from Blob, you basically have a buffer full of data.

That buffer isn't going to dynamically update itself, based on changes elsewhere in the OS, nor does it support callback options to do so.

Alternatively, from a blob or a file, you have the option to use URL.createObjectURL( file ), which returns a temporary url, which references a file, rather than the content of the file.

That said, any change to that file might then be reflected from subsequent calls to that URI.
This isn't something I've built to test, yet.

There would be no callback; however, you could set up an interval-based heartbeat, to make an XHR call to that URI, and then compare the .responseText with the previous .responseText.

Again, no guarantees, but that's as close as I think you're going to get to an answer, right now (while still in the realm of plugin/extension-free solutions), and might just be worth an hour of working out a prototype, and a couple more, testing support (whether the link is live, rather than an initial representation, etc).

var input = document.querySelector("input[type='file']"), // client must open file, themselves
    fileHandle = "", // this will be the url for the local file
    content    = "", // this will be the latest contents of the file
    previousContent = ""; // this will be the previous contents

var ms = 1000,
    secs = 2,

    pollId; // will be the process ID for the polling (so you can stop checking for changes, later).

// wait for a file to be selected
input.addEventListener("change", function (evt) {

    var file = evt.target.files[0]; // grab the file object
    fileHandle = URL.createObjectURL(file); // create a url which points to the local file

    // create an interval to check for changes
    pollId = setInterval(
        getLatest(fileHandle, getCurrent, updateCurrent),
        secs * ms
     );
});

function updateCurrent (latest) {
    current = latest;
    doStuff(current);
    // the text has changed; it's been updated;
    // now call home or do something else
}

function getCurrent () { return current; }

function getLatest (url, getCurrent, onchange) {
    return function () {
        // this isn't actually calling the network
        // it's calling the local file
        var xhr = new XMLHttpRequest();
        xhr.open("GET", url);

        xhr.onload = function () {
            var latest = xhr.responseText;
            if (getCurrent() !== latest) { onchange(latest); }
        };

        xhr.send();
    };
}

You now have change polling, in supporting browsers.

查看更多
登录 后发表回答