使用HTML5 File API检查文件是否已更改

Luk*_*uke 9 javascript html5

好的,所以我有一个程序可以将一些特定的数据输出到制表符分隔的变量文件中.

我一直在使用Excel打开并查看文件内容,但是我发现excel坚持要锁定它打开的每个文件都非常烦人,因为如果我在Excel中打开文件我的程序会崩溃...但我真的很喜欢每次运行程序后数据都要整齐地更新,所以我不必一直关闭并重新打开文件.

因此,我决定使用Javascript解析文件并将其显示在html表中是最简单的,而且确实如此.我立刻把东西撞到了一起.现在,如果我将文件保留在显示器上,我的程序不会崩溃,但是,它仍然不会更新......我每次都必须打开新生成的文件.

所以,我想知道是否有一种机制可以通过其他进程以某种方式通知我的Javascript对文件的更改?我知道这不太可能,但我想避免简单地轮询文件,原因很明显.

我对JS非常熟悉,但HTML5和新API对我来说都是新手.

T.J*_*der 10

我不相信File API有任何文件更改事件,只是进度事件等.

你可以使用民意调查.记住lastModifiedDateFile,然后当你的查询功能火灾,得到一个新的File实例的输入,看看是否lastModifiedDate已经改变.

这适用于Chrome,例如:Live Copy | 资源

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Watch for a file change</title>
<style type='text/css'>
body {
    font-family: sans-serif;
}
</style>
</head>
<body>
<input type='file' id='filename'>
<input type='button' id='btnStart' value='Start'>
<script type='text/javascript'>
(function() {
    var input;
    var lastMod;

    document.getElementById('btnStart').onclick = function() {
        startWatching();
    };
    function startWatching() {
        var file;

        if (typeof window.FileReader !== 'function') {
            display("The file API isn't supported on this browser yet.");
            return;
        }

        input = document.getElementById('filename');
        if (!input) {
            display("Um, couldn't find the filename element.");
        }
        else if (!input.files) {
            display("This browser doesn't seem to support the `files` property of file inputs.");
        }
        else if (!input.files[0]) {
            display("Please select a file before clicking 'Show Size'");
        }
        else {
            file = input.files[0];
            lastMod = file.lastModifiedDate;
            display("Last modified date: " + lastMod);
            display("Change the file");
            setInterval(tick, 250);
        }
    }

    function tick() {
        var file = input.files && input.files[0];
        if (file && lastMod && file.lastModifiedDate.getTime() !== lastMod.getTime()) {
            lastMod = file.lastModifiedDate;
            display("File changed: " + lastMod);
        }
    }

    function display(msg) {
        var p = document.createElement('p');
        p.innerHTML = msg;
        document.body.appendChild(p);
    }
})();
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

  • Firefox似乎缓存了文件,每次都生成相同的日期. (3认同)

End*_*ess 6

这个问题有两种解决方案,但<input type="file">不是其中之一。根据规范,它创建文件的“快照”。


本机文件系统

api是实验性的,需要在眨眼(也称为 chromium 浏览器)中启用标志。这个想法是,您获得一个文件句柄,当您需要该文件时,您可以调用异步“getFile”函数来检索实际文件。

此功能是一项“强大功能”,要求您的网站是安全的,并且它无法在沙盒 iframe 中工作。

因此,未经测试,这里有一些“黑暗中的代码”:

// triggerd on click
async function pickFile () {
  const handle = showOpenFilePicker()
  let lastModificationTime = 0
  
  async function compare () {
    const file = await handle.getFile()
    if (file.lastModified > lastModificationTime) {
      lastModificationTime = +file.lastModified
      console.log(await file.text())
    }
  }
  
  setInterval(compare, 1000)
}
Run Code Online (Sandbox Code Playgroud)

通过拖放获取条目

与本机文件系统类似,您也可以检索文件句柄并执行相同的操作,但此功能适用于当今的所有浏览器。但是这个代码片段在 stackoverflow 中不起作用,因为它使用了一些沙箱,使其不兼容,所以这里有一些注释

function drop(event) {
  event.stopPropagation();
  event.preventDefault();
    
  // get the file as an fileEntry (aka file handle)
  const fileEntry = event.dataTransfer.items[0].webkitGetAsEntry()
  let lastModificationTime = 0
  
  async function read (file) {
    // use the new async read method on blobs.
    console.log(await file.text())
  }
  
  function compare (meta) {
    if (meta.modificationTime > lastModificationTime) {
      lastModificationTime = meta.modificationTime
      fileEntry.file(read)
    }
  }
  
  setInterval(fileEntry.getMetadata.bind(fileEntry, compare), 1000)
}
Run Code Online (Sandbox Code Playgroud)

编辑:现在还有一种方法可以将文件拖放到 FileSystemFileHandle 中,使用起来更好

// triggerd on click
async function pickFile () {
  const handle = showOpenFilePicker()
  let lastModificationTime = 0
  
  async function compare () {
    const file = await handle.getFile()
    if (file.lastModified > lastModificationTime) {
      lastModificationTime = +file.lastModified
      console.log(await file.text())
    }
  }
  
  setInterval(compare, 1000)
}
Run Code Online (Sandbox Code Playgroud)